diff options
author | wtc%netscape.com <devnull@localhost> | 2002-06-04 20:36:22 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 2002-06-04 20:36:22 +0000 |
commit | 302a99e6fc9ac2a118a7d2ee0ab90c82fdb22036 (patch) | |
tree | 17b7a3a50c5107e801c6da41498d7568fb39917d | |
parent | 43341b5c97b80aab89f6281c29352d7c26bfd107 (diff) | |
download | nss-hg-302a99e6fc9ac2a118a7d2ee0ab90c82fdb22036.tar.gz |
Tracking bug 145836: check in NSS bug fixes for Mozilla 1.0.1. Approved by
drivers@mozilla.org and Netscape's ADT. (Tag: MOZILLA_1_0_BRANCH)
150 files changed, 10174 insertions, 5950 deletions
diff --git a/security/coreconf/HP-UXB.11.mk b/security/coreconf/HP-UXB.11.mk index 08463214d..5b489014f 100644 --- a/security/coreconf/HP-UXB.11.mk +++ b/security/coreconf/HP-UXB.11.mk @@ -41,14 +41,22 @@ endif ifndef NS_USE_GCC CCC = /opt/aCC/bin/aCC -ext ifeq ($(USE_64), 1) - OS_CFLAGS += -Aa +e +DA2.0W +DS2.0 +DChpux + ifeq ($(OS_TEST), ia64) + OS_CFLAGS += -Aa +e +p +DD64 + else + OS_CFLAGS += -Aa +e +DA2.0W +DS2.0 +DChpux + endif # Next line replaced by generic name handling in arch.mk # COMPILER_TAG = _64 else - ifdef USE_HYBRID - OS_CFLAGS += -Aa +e +DA2.0 +DS2.0 + ifeq ($(OS_TEST), ia64) + OS_CFLAGS += -Aa +e +p +DD32 else - OS_CFLAGS += +DAportable +DS2.0 + ifdef USE_HYBRID + OS_CFLAGS += -Aa +e +DA2.0 +DS2.0 + else + OS_CFLAGS += +DAportable +DS2.0 + endif endif endif else diff --git a/security/coreconf/config.mk b/security/coreconf/config.mk index 7ad0d1e16..01b633be8 100644 --- a/security/coreconf/config.mk +++ b/security/coreconf/config.mk @@ -58,7 +58,7 @@ endif # one for each OS release. # ####################################################################### -TARGET_OSES = FreeBSD BSD_OS NetBSD OpenUNIX OS2 QNX Darwin BeOS +TARGET_OSES = FreeBSD BSD_OS NetBSD OpenUNIX OS2 QNX Darwin BeOS OpenBSD ifeq (,$(filter-out $(TARGET_OSES),$(OS_TARGET))) include $(CORE_DEPTH)/coreconf/$(OS_TARGET).mk diff --git a/security/coreconf/jdk.mk b/security/coreconf/jdk.mk index 9e0151023..8189808c8 100644 --- a/security/coreconf/jdk.mk +++ b/security/coreconf/jdk.mk @@ -118,7 +118,7 @@ ifeq ($(OS_ARCH), WINNT) endif # set [Sun Solaris] platforms -ifeq ($(OS_TARGET), SunOS) +ifeq ($(OS_ARCH), SunOS) JAVA_CLASSES = $(JAVA_HOME)/lib/classes.zip ifeq ($(JRE_HOME),) @@ -139,7 +139,11 @@ ifeq ($(OS_TARGET), SunOS) INCLUDES += -I$(JAVA_HOME)/include/$(JAVA_ARCH) # (3) specify "linker" information +ifeq ($(USE_64), 1) + JAVA_CPU = $(shell uname -p)v9 +else JAVA_CPU = $(shell uname -p) +endif ifeq ($(JDK_VERSION), 1.1) JAVA_LIBDIR = lib/$(JAVA_CPU) @@ -153,7 +157,11 @@ endif JAVA_CLIBS = -lthread ifneq ($(JDK_VERSION), 1.1) +ifeq ($(USE_64), 1) + JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR)/server +else JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR)/classic +endif JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR) JAVA_LIBS += -ljvm -ljava else @@ -168,7 +176,7 @@ endif endif # set [Hewlett Packard HP-UX] platforms -ifeq ($(OS_TARGET), HP-UX) +ifeq ($(OS_ARCH), HP-UX) JAVA_CLASSES = $(JAVA_HOME)/lib/classes.zip ifeq ($(JRE_HOME),) @@ -207,7 +215,7 @@ ifeq ($(OS_TARGET), HP-UX) endif # set [Redhat Linux] platforms -ifeq ($(OS_TARGET), Linux) +ifeq ($(OS_ARCH), Linux) JAVA_CLASSES = $(JAVA_HOME)/lib/classes.zip ifeq ($(JRE_HOME),) @@ -235,7 +243,11 @@ ifeq ($(OS_TARGET), Linux) JAVA_CLIBS = JAVA_LIBS = -L$(JAVA_HOME)/$(JAVA_LIBDIR)/$(JDK_THREADING_MODEL) -lhpi - JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR)/classic -ljvm + ifeq ($(JDK_VERSION), 1.4) + JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR)/server -ljvm + else + JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR)/classic -ljvm + endif JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR) -ljava JAVA_LIBS += $(JAVA_CLIBS) @@ -246,7 +258,7 @@ ifeq ($(OS_TARGET), Linux) endif # set [IBM AIX] platforms -ifeq ($(OS_TARGET), AIX) +ifeq ($(OS_ARCH), AIX) JAVA_CLASSES = $(JAVA_HOME)/lib/classes.zip ifeq ($(JRE_HOME),) @@ -285,7 +297,7 @@ ifeq ($(OS_TARGET), AIX) endif # set [Digital UNIX] platforms -ifeq ($(OS_TARGET), OSF1) +ifeq ($(OS_ARCH), OSF1) JAVA_CLASSES = $(JAVA_HOME)/lib/classes.zip ifeq ($(JRE_HOME),) @@ -324,7 +336,7 @@ ifeq ($(OS_TARGET), OSF1) endif # set [Silicon Graphics IRIX] platforms -ifeq ($(OS_TARGET), IRIX) +ifeq ($(OS_ARCH), IRIX) JAVA_CLASSES = $(JAVA_HOME)/lib/dev.jar:$(JAVA_HOME)/lib/rt.jar ifeq ($(JRE_HOME),) @@ -396,6 +408,9 @@ ifeq ($(JDK_CLASSPATH_OPT),) JDK_CLASSPATH_OPT = -classpath $(JDK_CLASSPATH) endif +ifeq ($(USE_64), 1) + JDK_USE_64 = -d64 +endif endif @@ -437,6 +452,7 @@ ifeq ($(JAVA),) JAVA_FLAGS += $(JDK_DEBUG_OPT) JAVA_FLAGS += $(JDK_CLASSPATH_OPT) JAVA_FLAGS += $(JDK_JIT_OPT) + JAVA_FLAGS += $(JDK_USE_64) JAVA = $(JAVA_PROG) $(JAVA_FLAGS) endif @@ -451,6 +467,7 @@ ifeq ($(JAVAC),) JAVAC_FLAGS += $(JDK_DEBUG_OPT) JAVAC_FLAGS += $(JDK_CLASSPATH_OPT) JAVAC_FLAGS += $(JDK_CLASS_REPOSITORY_OPT) + JAVAC_FLAGS += $(JDK_USE_64) JAVAC = $(JAVAC_PROG) $(JAVAC_FLAGS) endif diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index 772c7d215..adaa87d77 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -233,13 +233,13 @@ GetCertRequest(PRFileDesc *inFile, PRBool ascii) data */ PORT_Memset(&signedData, 0, sizeof(signedData)); - rv = SEC_ASN1DecodeItem(arena, &signedData, CERT_SignedDataTemplate, - &reqDER); + rv = SEC_ASN1DecodeItem(arena, &signedData, + SEC_ASN1_GET(CERT_SignedDataTemplate), &reqDER); if (rv) break; - rv = SEC_ASN1DecodeItem(arena, certReq, CERT_CertificateRequestTemplate, - &signedData.data); + rv = SEC_ASN1DecodeItem(arena, certReq, + SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data); } while (0); if (rv) { @@ -308,42 +308,12 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, GEN_BREAK(SECFailure); } -#ifdef notdef - /* CERT_ImportCert only collects certificates and returns the - * first certficate. It does not insert these certificates into - * the dbase. For now, just call CERT_NewTempCertificate. - * This will result in decoding the der twice. This have to - * be handle properly. - */ - - tempCert = CERT_NewTempCertificate(handle, &cert->derCert, NULL, - PR_FALSE, PR_TRUE); - - if (!PK11_IsInternal(slot)) { - tempCert->trust = trust; - - rv = PK11_ImportCertForKeyToSlot(slot, tempCert, name, - PR_FALSE, NULL); - } - - if (tempCert == NULL) { - SECU_PrintError(progName,"unable to add cert to the temp database"); - GEN_BREAK(SECFailure); - } - - rv = CERT_AddTempCertToPerm(tempCert, name, trust); - if (rv) { - SECU_PrintError(progName, "could not add certificate to database"); - GEN_BREAK(SECFailure); - } - - if ( emailcert ) - CERT_SaveSMimeProfile(tempCert, NULL, NULL); -#else - rv = PK11_Authenticate(slot, PR_TRUE, pwdata); - if (rv != SECSuccess) { - SECU_PrintError(progName, "could authenticate to token or database"); - GEN_BREAK(SECFailure); + if (!PK11_IsFriendly(slot)) { + rv = PK11_Authenticate(slot, PR_TRUE, pwdata); + if (rv != SECSuccess) { + SECU_PrintError(progName, "could not authenticate to token or database"); + GEN_BREAK(SECFailure); + } } rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE); @@ -362,12 +332,8 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, CERT_SaveSMimeProfile(cert, NULL, pwdata); } -#endif } while (0); -#ifdef notdef - CERT_DestroyCertificate (tempCert); -#endif CERT_DestroyCertificate (cert); PORT_Free(trust); PORT_Free(certDER.data); @@ -409,7 +375,7 @@ CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, /* Der encode the request */ encoding = SEC_ASN1EncodeItem(arena, NULL, cr, - CERT_CertificateRequestTemplate); + SEC_ASN1_GET(CERT_CertificateRequestTemplate)); if (encoding == NULL) { SECU_PrintError(progName, "der encoding of request failed"); return SECFailure; @@ -530,6 +496,7 @@ ChangeTrustAttributes(CERTCertDBHandle *handle, char *name, char *trusts) SECU_PrintError(progName, "unable to modify trust attributes"); return SECFailure; } + CERT_DestroyCertificate(cert); return SECSuccess; } @@ -577,6 +544,7 @@ dumpChain(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, return SECFailure; } chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE); + CERT_DestroyCertificate(the_cert); if (!chain) { SECU_PrintError(progName, "Could not obtain chain for: %s\n", name); return SECFailure; @@ -586,7 +554,9 @@ dumpChain(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, c = CERT_FindCertByDERCert(handle, &chain->certs[i]); for (j=i; j<chain->len-1; j++) printf(" "); printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName); + CERT_DestroyCertificate(c); } + CERT_DestroyCertificateList(chain); return SECSuccess; } @@ -597,86 +567,53 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, CERTCertificate *cert; SECItem data; PRInt32 numBytes; - SECStatus rv; + SECStatus rv = SECFailure; -#ifdef nodef - /* For now, split handling of slot to internal vs. other. slot should - * probably be allowed to be NULL so that all slots can be listed. - * In that case, need to add a call to PK11_TraverseSlotCerts(). - */ - if (PK11_IsInternal(slot)) { - if (name == NULL) { - /* Print all certs in internal slot db. */ - rv = SECU_PrintCertificateNames(handle, PR_STDOUT, - PR_FALSE, PR_TRUE); - if (rv) { - SECU_PrintError(progName, - "problem printing certificate nicknames"); - return SECFailure; - } - } else if (raw || ascii) { - /* Dump binary or ascii DER for the cert to stdout. */ - cert = CERT_FindCertByNicknameOrEmailAddr(handle, name); - if (!cert) { - SECU_PrintError(progName, - "could not find certificate named \"%s\"", name); - return SECFailure; - } - data.data = cert->derCert.data; - data.len = cert->derCert.len; - if (ascii) { - PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, + /* List certs on a non-internal slot. */ + if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) + PK11_Authenticate(slot, PR_TRUE, pwarg); + if (name) { + CERTCertificate *the_cert; + the_cert = PK11_FindCertFromNickname(name, NULL); + if (!the_cert) { + SECU_PrintError(progName, "Could not find: %s\n", name); + return SECFailure; + } + data.data = the_cert->derCert.data; + data.len = the_cert->derCert.len; + if (ascii) { + PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER); - } else if (raw) { - numBytes = PR_Write(outfile, data.data, data.len); - if (numBytes != data.len) { - SECU_PrintSystemError(progName, "error writing raw cert"); - return SECFailure; - } + rv = SECSuccess; + } else if (raw) { + numBytes = PR_Write(outfile, data.data, data.len); + if (numBytes != data.len) { + SECU_PrintSystemError(progName, "error writing raw cert"); + rv = SECFailure; } + rv = SECSuccess; } else { - /* Pretty-print cert. */ - rv = CERT_TraversePermCertsForNickname(handle, name, printCertCB, - NULL); + rv = printCertCB(the_cert, the_cert->trust); } + CERT_DestroyCertificate(the_cert); } else { -#endif - /* List certs on a non-internal slot. */ - if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) - PK11_Authenticate(slot, PR_TRUE, pwarg); - if (name) { - CERTCertificate *the_cert; - the_cert = PK11_FindCertFromNickname(name, NULL); - if (!the_cert) { - SECU_PrintError(progName, "Could not find: %s\n", name); - return SECFailure; + CERTCertList *certs; + CERTCertListNode *node; + + certs = PK11_ListCertsInSlot(slot); + if (certs) { + for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs); + node = CERT_LIST_NEXT(node)) { + SECU_PrintCertNickname(node->cert,stdout); } - data.data = the_cert->derCert.data; - data.len = the_cert->derCert.len; - if (ascii) { - PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, - BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER); - rv = SECSuccess; - } else if (raw) { - numBytes = PR_Write(outfile, data.data, data.len); - if (numBytes != data.len) { - SECU_PrintSystemError(progName, "error writing raw cert"); - rv = SECFailure; - } - rv = SECSuccess; - } else { - rv = printCertCB(the_cert, the_cert->trust); - } - } else { - rv = PK11_TraverseCertsInSlot(slot, SECU_PrintCertNickname, stdout); - } - if (rv) { - SECU_PrintError(progName, "problem printing certificate nicknames"); - return SECFailure; + CERT_DestroyCertList(certs); + rv = SECSuccess; } -#ifdef notdef } -#endif + if (rv) { + SECU_PrintError(progName, "problem printing certificate nicknames"); + return SECFailure; + } return SECSuccess; /* not rv ?? */ } @@ -742,6 +679,7 @@ DeleteCert(CERTCertDBHandle *handle, char *name) } rv = SEC_DeletePermCertificate(cert); + CERT_DestroyCertificate(cert); if (rv) { SECU_PrintError(progName, "unable to delete certificate"); return SECFailure; @@ -755,7 +693,7 @@ ValidateCert(CERTCertDBHandle *handle, char *name, char *date, char *certUsage, PRBool checkSig, PRBool logit, secuPWData *pwdata) { SECStatus rv; - CERTCertificate *cert; + CERTCertificate *cert = NULL; int64 timeBoundary; SECCertUsage usage; CERTVerifyLog reallog; @@ -844,84 +782,13 @@ ValidateCert(CERTCertDBHandle *handle, char *name, char *date, } } while (0); - return (rv); -} - -#ifdef notdef -static SECStatus -DumpPublicKey(int dbindex, char *nickname, FILE *out) -{ - SECKEYLowPrivateKey *privKey; - SECKEYLowPublicKey *publicKey; - - if (dbindex) { - /*privKey = secu_GetPrivKeyFromIndex(dbindex);*/ - } else { - privKey = GetPrivKeyFromNickname(nickname); + if (cert) { + CERT_DestroyCertificate(cert); } - publicKey = SECKEY_LowConvertToPublicKey(privKey); - /* Output public key (in the clear) */ - switch(publicKey->keyType) { - case rsaKey: - fprintf(out, "RSA Public-Key:\n"); - SECU_PrintInteger(out, &publicKey->u.rsa.modulus, "modulus", 1); - SECU_PrintInteger(out, &publicKey->u.rsa.publicExponent, - "publicExponent", 1); - break; - case dsaKey: - fprintf(out, "DSA Public-Key:\n"); - SECU_PrintInteger(out, &publicKey->u.dsa.params.prime, "prime", 1); - SECU_PrintInteger(out, &publicKey->u.dsa.params.subPrime, - "subPrime", 1); - SECU_PrintInteger(out, &publicKey->u.dsa.params.base, "base", 1); - SECU_PrintInteger(out, &publicKey->u.dsa.publicValue, "publicValue", 1); - break; - default: - fprintf(out, "unknown key type\n"); - break; - } - return SECSuccess; + return (rv); } -static SECStatus -DumpPrivateKey(int dbindex, char *nickname, FILE *out) -{ - SECKEYLowPrivateKey *key; - if (dbindex) { - /*key = secu_GetPrivKeyFromIndex(dbindex);*/ - } else { - key = GetPrivKeyFromNickname(nickname); - } - - switch(key->keyType) { - case rsaKey: - fprintf(out, "RSA Private-Key:\n"); - SECU_PrintInteger(out, &key->u.rsa.modulus, "modulus", 1); - SECU_PrintInteger(out, &key->u.rsa.publicExponent, "publicExponent", 1); - SECU_PrintInteger(out, &key->u.rsa.privateExponent, - "privateExponent", 1); - SECU_PrintInteger(out, &key->u.rsa.prime1, "prime1", 1); - SECU_PrintInteger(out, &key->u.rsa.prime2, "prime2", 1); - SECU_PrintInteger(out, &key->u.rsa.exponent1, "exponent2", 1); - SECU_PrintInteger(out, &key->u.rsa.exponent2, "exponent2", 1); - SECU_PrintInteger(out, &key->u.rsa.coefficient, "coefficient", 1); - break; - case dsaKey: - fprintf(out, "DSA Private-Key:\n"); - SECU_PrintInteger(out, &key->u.dsa.params.prime, "prime", 1); - SECU_PrintInteger(out, &key->u.dsa.params.subPrime, "subPrime", 1); - SECU_PrintInteger(out, &key->u.dsa.params.base, "base", 1); - SECU_PrintInteger(out, &key->u.dsa.publicValue, "publicValue", 1); - SECU_PrintInteger(out, &key->u.dsa.privateValue, "privateValue", 1); - break; - default: - fprintf(out, "unknown key type\n"); - break; - } - return SECSuccess; -} -#endif static SECStatus printKeyCB(SECKEYPublicKey *key, SECItem *data, void *arg) @@ -936,31 +803,19 @@ printKeyCB(SECKEYPublicKey *key, SECItem *data, void *arg) return SECSuccess; } -struct secuCBData { - FILE *file; - int keycount; - void *wincx; -}; - /* callback for listing certs through pkcs11 */ static SECStatus -secu_PrintKeyFromCert(CERTCertificate *cert, void *data) +secu_PrintKey(FILE *out, int count, SECKEYPrivateKey *key) { - FILE *out; - struct secuCBData *cbdata; - SECKEYPrivateKey *key; - - cbdata = (struct secuCBData *)data; - out = cbdata->file; - key = PK11_FindPrivateKeyFromCert(cert->slot, cert, cbdata->wincx); - if (!key) { - fprintf(out, "XXX could not extract key for %s.\n", cert->nickname); - return SECFailure; - } - /* XXX should have a type field also */ - fprintf(out, "<%d> %s\n", 0, cert->nickname); + char *name; - cbdata->keycount++; + name = PK11_GetPrivateKeyNickname(key); + if (name == NULL) { + /* should look up associated cert */ + name = PORT_Strdup("< orphaned >"); + } + fprintf(out, "<%d> %s\n", count, name); + PORT_Free(name); return SECSuccess; } @@ -968,43 +823,29 @@ secu_PrintKeyFromCert(CERTCertificate *cert, void *data) static SECStatus listKeys(PK11SlotInfo *slot, KeyType keyType, void *pwarg) { - SECStatus rv = SECSuccess; - struct secuCBData cbdata; + SECKEYPrivateKeyList *list; + SECKEYPrivateKeyListNode *node; + int count; - cbdata.keycount = 0; - cbdata.file = stdout; - cbdata.wincx = pwarg; - -#ifdef notdef - if (PK11_IsInternal(slot)) { - /* Print all certs in internal slot db. */ - rv = SECU_PrintKeyNames(SECKEY_GetDefaultKeyDB(), stdout); - if (rv) { - SECU_PrintError(progName, "problem listing keys"); - return SECFailure; - } - } else { -#endif - /* XXX need a function as below */ - /* could iterate over certs on slot and print keys */ - /* this would miss stranded keys */ - /*rv = PK11_TraverseSlotKeys(slotname, keyType, printKeyCB, NULL, NULL);*/ - if (PK11_NeedLogin(slot)) + if (PK11_NeedLogin(slot)) PK11_Authenticate(slot, PR_TRUE, pwarg); - rv = PK11_TraverseCertsInSlot(slot, secu_PrintKeyFromCert, &cbdata); - if (rv) { - SECU_PrintError(progName, "problem listing keys"); - return SECFailure; - } - if (cbdata.keycount == 0) { - SECU_PrintError(progName, "no keys found"); - return SECFailure; - } - return SECSuccess; -#ifdef notdef + + list = PK11_ListPrivateKeysInSlot(slot); + if (list == NULL) { + SECU_PrintError(progName, "problem listing keys"); + return SECFailure; } - return rv; -#endif + for (count=0, node=PRIVKEY_LIST_HEAD(list) ; !PRIVKEY_LIST_END(node,list); + node= PRIVKEY_LIST_NEXT(node),count++) { + secu_PrintKey(stdout, count, node->key); + } + SECKEY_DestroyPrivateKeyList(list); + + if (count == 0) { + SECU_PrintError(progName, "no keys found"); + return SECFailure; + } + return SECSuccess; } static SECStatus @@ -1013,19 +854,6 @@ ListKeys(PK11SlotInfo *slot, char *keyname, int index, { SECStatus rv = SECSuccess; -#ifdef notdef - if (keyname) { - if (dopriv) { - return DumpPrivateKey(index, keyname, stdout); - } else { - return DumpPublicKey(index, keyname, stdout); - } - } -#endif - /* For now, split handling of slot to internal vs. other. slot should - * probably be allowed to be NULL so that all slots can be listed. - * In that case, need to add a call to PK11_TraverseSlotCerts(). - */ if (slot == NULL) { PK11SlotList *list; PK11SlotListElement *le; @@ -1051,11 +879,16 @@ DeleteKey(char *nickname, secuPWData *pwdata) if (PK11_NeedLogin(slot)) PK11_Authenticate(slot, PR_TRUE, pwdata); cert = PK11_FindCertFromNickname(nickname, pwdata); - if (!cert) return SECFailure; + if (!cert) { + PK11_FreeSlot(slot); + return SECFailure; + } rv = PK11_DeleteTokenCertAndKey(cert, pwdata); if (rv != SECSuccess) { SECU_PrintError("problem deleting private key \"%s\"\n", nickname); } + CERT_DestroyCertificate(cert); + PK11_FreeSlot(slot); return rv; } @@ -1565,6 +1398,14 @@ CreateOidSequence(void) return (CERTOidSequence *)NULL; } +static void +DestroyOidSequence(CERTOidSequence *os) +{ + if (os->arena) { + PORT_FreeArena(os->arena, PR_FALSE); + } +} + static SECStatus AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag) { @@ -1604,11 +1445,19 @@ AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag) return SECSuccess; } +SEC_ASN1_MKSUB(SEC_ObjectIDTemplate); + +const SEC_ASN1Template CERT_OidSeqTemplate[] = { + { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, + offsetof(CERTOidSequence, oids), + SEC_ASN1_SUB(SEC_ObjectIDTemplate) } +}; + + static SECItem * EncodeOidSequence(CERTOidSequence *os) { SECItem *rv; - extern const SEC_ASN1Template CERT_OidSeqTemplate[]; rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem)); if( (SECItem *)NULL == rv ) { @@ -1697,7 +1546,7 @@ AddExtKeyUsage (void *extHandle) ? PR_TRUE : PR_FALSE), PR_TRUE); /*FALLTHROUGH*/ loser: - CERT_DestroyOidSequence(os); + DestroyOidSequence(os); return rv; } @@ -1809,7 +1658,7 @@ AddBasicConstraint(void *extHandle) static SECItem * SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign, -SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg) +SECKEYPrivateKey *privKey, char *issuerNickName, void *pwarg) { SECItem der; SECItem *result = NULL; @@ -1819,10 +1668,7 @@ SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg) SECOidTag algID; void *dummy; - if( selfsign ) { - caPrivateKey = selfsignprivkey; - } else { - /*CERTCertificate *issuer = CERT_FindCertByNickname(handle, issuerNickName);*/ + if( !selfsign ) { CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg); if( (CERTCertificate *)NULL == issuer ) { SECU_PrintError(progName, "unable to find issuer with nickname %s", @@ -1830,7 +1676,8 @@ SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg) return (SECItem *)NULL; } - caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg); + privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg); + CERT_DestroyCertificate(issuer); if (caPrivateKey == NULL) { SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName); return NULL; @@ -1839,7 +1686,7 @@ SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg) arena = cert->arena; - switch(caPrivateKey->keyType) { + switch(privKey->keyType) { case rsaKey: algID = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; break; @@ -1864,7 +1711,8 @@ SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg) der.len = 0; der.data = NULL; - dummy = SEC_ASN1EncodeItem (arena, &der, cert, CERT_CertificateTemplate); + dummy = SEC_ASN1EncodeItem (arena, &der, cert, + SEC_ASN1_GET(CERT_CertificateTemplate)); if (!dummy) { fprintf (stderr, "Could not encode certificate.\n"); goto done; @@ -1876,7 +1724,7 @@ SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg) goto done; } - rv = SEC_DerSignData (arena, result, der.data, der.len, caPrivateKey, + rv = SEC_DerSignData (arena, result, der.data, der.len, privKey, algID); if (rv != SECSuccess) { fprintf (stderr, "Could not sign encoded certificate data.\n"); @@ -1886,7 +1734,9 @@ SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg) } cert->derCert = *result; done: - SECKEY_DestroyPrivateKey(caPrivateKey); + if (caPrivateKey) { + SECKEY_DestroyPrivateKey(caPrivateKey); + } return result; } @@ -2331,7 +2181,7 @@ main(int argc, char **argv) secuPWData pwdata = { PW_NONE, 0 }; PRBool readOnly = PR_FALSE; - SECKEYPrivateKey *privkey; + SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; int i; @@ -2873,15 +2723,16 @@ main(int argc, char **argv) } shutdown: - if (slot) + if (slot) { PK11_FreeSlot(slot); -#ifdef notdef - if ( certHandle ) { - CERT_ClosePermCertDB(certHandle); } -#else + if (privkey) { + SECKEY_DestroyPrivateKey(privkey); + } + if (pubkey) { + SECKEY_DestroyPublicKey(pubkey); + } NSS_Shutdown(); -#endif if (rv == SECSuccess) { return 0; diff --git a/security/nss/cmd/certutil/keystuff.c b/security/nss/cmd/certutil/keystuff.c index 2926f8f1b..317443a27 100644 --- a/security/nss/cmd/certutil/keystuff.c +++ b/security/nss/cmd/certutil/keystuff.c @@ -68,6 +68,14 @@ extern char *sys_errlist[]; #define ERROR_BREAK rv = SECFailure;break; +const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) }, + { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) }, + { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) }, + { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) }, + { 0, } +}; + /* returns 0 for success, -1 for failure (EOF encountered) */ static int UpdateRNG(void) @@ -126,8 +134,7 @@ UpdateRNG(void) rv = -1; break; } - RNG_GetNoise(&randbuf[1], sizeof(randbuf)-1); - RNG_RandomUpdate(randbuf, sizeof(randbuf)); + PK11_RandomUpdate(randbuf, sizeof(randbuf)); if (c != randbuf[0]) { randbuf[0] = c; FPS "\r|"); @@ -189,27 +196,27 @@ static unsigned char G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02 }; -static PQGParams default_pqg_params = { +static SECKEYPQGParams default_pqg_params = { NULL, { 0, P, sizeof(P) }, { 0, Q, sizeof(Q) }, { 0, G, sizeof(G) } }; -static PQGParams * +static SECKEYPQGParams * decode_pqg_params(char *str) { char *buf; unsigned int len; PRArenaPool *arena; - PQGParams *params; + SECKEYPQGParams *params; SECStatus status; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) return NULL; - params = PORT_ArenaZAlloc(arena, sizeof(PQGParams)); + params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams)); if (params == NULL) goto loser; params->arena = arena; @@ -229,11 +236,19 @@ loser: PORT_FreeArena(arena, PR_FALSE); return NULL; } - + +void +CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params) +{ + if (params->arena) { + PORT_FreeArena(params->arena, PR_FALSE); + } +} + static int pqg_prime_bits(char *str) { - PQGParams *params = NULL; + SECKEYPQGParams *params = NULL; int primeBits = 0, i; params = decode_pqg_params(str); @@ -246,7 +261,7 @@ pqg_prime_bits(char *str) done: if (params != NULL) - PQG_DestroyParams(params); + CERTUTIL_DestroyParamsPQG(params); return primeBits; } @@ -270,7 +285,7 @@ SECU_GetpqgString(char *filename) return NULL; } -PQGParams* +SECKEYPQGParams* getpqgfromfile(int keyBits, char *pqgFile) { char *end, *str, *pqgString; @@ -302,6 +317,26 @@ found_match: return decode_pqg_params(str); } +void CERTUTIL_FileForRNG(char *noise) +{ + char buf[2048]; + PRFileDesc *fd; + PRInt32 count; + + fd = PR_OpenFile(noise,PR_RDONLY,0666); + if (!fd) return; + + do { + count = PR_Read(fd,buf,sizeof(buf)); + if (count > 0) { + PK11_RandomUpdate(buf,count); + } + } while (count > 0); + + PR_Close(fd); + +} + SECKEYPrivateKey * CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, int publicExponent, char *noise, @@ -311,17 +346,16 @@ CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, CK_MECHANISM_TYPE mechanism; SECOidTag algtag; PK11RSAGenParams rsaparams; - PQGParams *dsaparams = NULL; + SECKEYPQGParams *dsaparams = NULL; void *params; PRArenaPool *dsaparena; /* * Do some random-number initialization. */ - RNG_SystemInfoForRNG(); if (noise) { - RNG_FileForRNG(noise); + CERTUTIL_FileForRNG(noise); } else { int rv = UpdateRNG(); if (rv) { @@ -346,7 +380,7 @@ CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, } else { dsaparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (dsaparena == NULL) return NULL; - dsaparams = PORT_ArenaZAlloc(dsaparena, sizeof(PQGParams)); + dsaparams = PORT_ArenaZAlloc(dsaparena, sizeof(SECKEYPQGParams)); if (dsaparams == NULL) return NULL; dsaparams->arena = dsaparena; SECITEM_AllocItem(dsaparena, &dsaparams->prime, sizeof P); diff --git a/security/nss/cmd/certutil/manifest.mn b/security/nss/cmd/certutil/manifest.mn index d387540b9..8d93b0116 100644 --- a/security/nss/cmd/certutil/manifest.mn +++ b/security/nss/cmd/certutil/manifest.mn @@ -49,4 +49,4 @@ REQUIRES = dbm seccmd PROGRAM = certutil -USE_STATIC_LIBS = 1 +#USE_STATIC_LIBS = 1 diff --git a/security/nss/cmd/crmf-cgi/crmfcgi.c b/security/nss/cmd/crmf-cgi/crmfcgi.c index c5fd2d451..72199cfd5 100644 --- a/security/nss/cmd/crmf-cgi/crmfcgi.c +++ b/security/nss/cmd/crmf-cgi/crmfcgi.c @@ -286,6 +286,7 @@ initNSS(CGIVarTable *varTable) PK11_SetPasswordFunc(passwordCallback); keySlot = PK11_GetInternalKeySlot(); rv = PK11_Authenticate(keySlot, PR_FALSE, varTable); + PK11_FreeSlot(keySlot); if (rv != SECSuccess) { return AUTH_FAILED; } diff --git a/security/nss/cmd/crmftest/testcrmf.c b/security/nss/cmd/crmftest/testcrmf.c index db9add0bc..42e02a38c 100644 --- a/security/nss/cmd/crmftest/testcrmf.c +++ b/security/nss/cmd/crmftest/testcrmf.c @@ -177,23 +177,28 @@ GetSubjectPubKeyInfo(SECKEYPrivateKey **destPrivKey, SECKEYPrivateKey *privKey = NULL; SECKEYPublicKey *pubKey = NULL; PK11SlotInfo *keySlot = NULL; + PK11SlotInfo *cryptoSlot = NULL; PK11RSAGenParams *rsaParams = NULL; PQGParams *dsaParams = NULL; keySlot = PK11_GetInternalKeySlot(); PK11_Authenticate(keySlot, PR_FALSE, NULL); - PK11_Authenticate(PK11_GetInternalSlot(), PR_FALSE, NULL); + cryptoSlot = PK11_GetInternalSlot(); + PK11_Authenticate(cryptoSlot, PR_FALSE, NULL); + PK11_FreeSlot(cryptoSlot); rsaParams = GetRSAParams(); privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN, (void*)rsaParams, &pubKey, PR_FALSE, PR_FALSE, NULL); /* dsaParams = GetDSAParams(); if (dsaParams == NULL) { + PK11_FreeSlot(keySlot); return NULL; } privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN, (void*)dsaParams, &pubKey, PR_FALSE, PR_FALSE, NULL);*/ + PK11_FreeSlot(keySlot); if (privKey == NULL || pubKey == NULL) { if (pubKey) { SECKEY_DestroyPublicKey(pubKey); diff --git a/security/nss/cmd/lib/seccnames.c b/security/nss/cmd/lib/seccnames.c index 833361e41..a1857dc0e 100644 --- a/security/nss/cmd/lib/seccnames.c +++ b/security/nss/cmd/lib/seccnames.c @@ -45,7 +45,9 @@ #include "secutil.h" #include "secpkcs7.h" #include "secrng.h" +#if !defined(_WIN32_WCE) #include <sys/stat.h> +#endif #include <stdarg.h> #ifdef XP_UNIX diff --git a/security/nss/cmd/lib/secpwd.c b/security/nss/cmd/lib/secpwd.c index 57c4aac5f..8bc4eef14 100644 --- a/security/nss/cmd/lib/secpwd.c +++ b/security/nss/cmd/lib/secpwd.c @@ -46,7 +46,7 @@ #include <unistd.h> #endif -#ifdef _WINDOWS +#if defined(_WINDOWS) && !defined(_WIN32_WCE) #include <conio.h> #include <io.h> #define QUIET_FGETS quiet_fgets @@ -82,13 +82,16 @@ static void echoOn(int fd) char *SEC_GetPassword(FILE *input, FILE *output, char *prompt, PRBool (*ok)(char *)) { - char phrase[200]; - int infd = fileno(input); #if defined(_WINDOWS) || defined(OS2) int isTTY = (input == stdin); +#define echoOn(x) +#define echoOff(x) #else + int infd = fileno(input); int isTTY = isatty(infd); #endif + char phrase[200]; + for (;;) { /* Prompt for password */ if (isTTY) { @@ -167,8 +170,11 @@ static char * quiet_fgets (char *buf, int length, FILE *input) while (1) { - c = getch(); - +#if defined (_WIN32_WCE) + c = getchar(); /* gets a character from stdin */ +#else + c = getch(); /* getch gets a character from the console */ +#endif if (c == '\b') { if (end > buf) diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c index f7cfb8d59..6b9ab8e3c 100644 --- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -41,13 +41,16 @@ #include "prerror.h" #include "prprf.h" #include "plgetopt.h" +#include "prenv.h" #include "secutil.h" #include "secpkcs7.h" #include "secrng.h" -#include <sys/stat.h> #include <stdarg.h> +#if !defined(_WIN32_WCE) +#include <sys/stat.h> #include <errno.h> +#endif #ifdef XP_UNIX #include <unistd.h> @@ -110,7 +113,11 @@ SECU_PrintSystemError(char *progName, char *msg, ...) va_start(args, msg); fprintf(stderr, "%s: ", progName); vfprintf(stderr, msg, args); +#if defined(_WIN32_WCE) + fprintf(stderr, ": %d\n", PR_GetOSError()); +#else fprintf(stderr, ": %s\n", strerror(errno)); +#endif va_end(args); } @@ -388,7 +395,7 @@ SECU_DefaultSSLDir(void) char *dir; static char sslDir[1000]; - dir = getenv("SSL_DIR"); + dir = PR_GetEnv("SSL_DIR"); if (!dir) return NULL; @@ -424,7 +431,7 @@ SECU_ConfigDirectory(const char* base) if (base == NULL || *base == 0) { - home = getenv("HOME"); + home = PR_GetEnv("HOME"); if (!home) home = ""; if (*home && home[strlen(home) - 1] == '/') @@ -1586,6 +1593,9 @@ SECU_PrintCertNickname(CERTCertificate *cert, void *data) if ( name == NULL ) { name = cert->emailAddr; } + if ( name == NULL ) { + name = "(NULL)"; + } trust = cert->trust; if (trust) { diff --git a/security/nss/cmd/modutil/modutil.c b/security/nss/cmd/modutil/modutil.c index bba34e69e..2f1886b47 100644 --- a/security/nss/cmd/modutil/modutil.c +++ b/security/nss/cmd/modutil/modutil.c @@ -912,6 +912,7 @@ main(int argc, char *argv[]) break; } + NSS_Shutdown(); loser: PR_Cleanup(); return errcode; diff --git a/security/nss/cmd/pk12util/pk12util.c b/security/nss/cmd/pk12util/pk12util.c index 6e2ec7d0d..a559c415d 100644 --- a/security/nss/cmd/pk12util/pk12util.c +++ b/security/nss/cmd/pk12util/pk12util.c @@ -476,7 +476,7 @@ P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot, PR_Close(p12cxt->file); p12cxt->file = NULL; - PK11_FreeSlot(slot); + /* PK11_FreeSlot(slot); */ rv = SECSuccess; @@ -832,6 +832,7 @@ main(int argc, char **argv) } done: + if (slot) PK11_FreeSlot(slot); NSS_Shutdown(); exit(pk12uErrno); } diff --git a/security/nss/cmd/platlibs.mk b/security/nss/cmd/platlibs.mk index a40e0a89f..0a8bfb567 100644 --- a/security/nss/cmd/platlibs.mk +++ b/security/nss/cmd/platlibs.mk @@ -75,7 +75,7 @@ EXTRA_LIBS += \ $(NULL) # $(PROGRAM) has NO explicit dependencies on $(OS_LIBS) -OS_LIBS += \ +#OS_LIBS += \ wsock32.lib \ winmm.lib \ $(NULL) @@ -155,7 +155,7 @@ EXTRA_LIBS += \ $(NULL) # $(PROGRAM) has NO explicit dependencies on $(OS_LIBS) -OS_LIBS += \ +#OS_LIBS += \ wsock32.lib \ winmm.lib \ $(NULL) diff --git a/security/nss/cmd/rsaperf/defkey.c b/security/nss/cmd/rsaperf/defkey.c index fe4870d77..3dd4fe36c 100644 --- a/security/nss/cmd/rsaperf/defkey.c +++ b/security/nss/cmd/rsaperf/defkey.c @@ -38,6 +38,7 @@ #include "secoidt.h" #include "lowkeyti.h" +#undef CONST #define CONST static CONST unsigned char default_n[128] = { diff --git a/security/nss/cmd/sdrtest/sdrtest.c b/security/nss/cmd/sdrtest/sdrtest.c index 3124ef6cf..9578b3472 100644 --- a/security/nss/cmd/sdrtest/sdrtest.c +++ b/security/nss/cmd/sdrtest/sdrtest.c @@ -233,7 +233,10 @@ file_loser: PK11_GetSlotName(slot)); return SECFailure; } + } + if (slot) { PK11_FreeSlot(slot); + slot == NULL; } rv = PK11SDR_Encrypt(&keyid, &data, &result, 0); diff --git a/security/nss/cmd/signtool/certgen.c b/security/nss/cmd/signtool/certgen.c index dd7128eaa..00222044d 100644 --- a/security/nss/cmd/signtool/certgen.c +++ b/security/nss/cmd/signtool/certgen.c @@ -45,8 +45,8 @@ static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts); static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type); static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk); -static CERTCertificate* install_cert(CERTCertDBHandle *db, PK11SlotInfo *slot, - SECItem *derCert, char *nickname); +static CERTCertificate* install_cert(CERTCertDBHandle *db, SECItem *derCert, + char *nickname); static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk, SECKEYPrivateKey **privk, int keysize); static CERTCertificateRequest* make_cert_request(char *subject, @@ -333,7 +333,7 @@ GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db, } derCert = sign_cert (temp_cert, privk); - cert = install_cert(db, slot, derCert, nickname); + cert = install_cert(db, derCert, nickname); if(ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) { FatalError("Unable to change trust on generated certificate"); } @@ -491,11 +491,9 @@ sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk) * Installs the cert in the permanent database. */ static CERTCertificate* -install_cert(CERTCertDBHandle *db, PK11SlotInfo *slot, SECItem *derCert, - char *nickname) +install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname) { CERTCertificate *newcert; - CERTCertTrust trust; PK11SlotInfo *newSlot; newcert = CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL); @@ -507,31 +505,12 @@ install_cert(CERTCertDBHandle *db, PK11SlotInfo *slot, SECItem *derCert, } newSlot = PK11_ImportCertForKey(newcert, nickname, NULL /*wincx*/); - if( slot == NULL ) { + if( newSlot == NULL ) { PR_fprintf(errorFD, "Unable to install certificate\n"); errorCount++; exit(ERRX); } - - PORT_Memset ((void *) &trust, 0, sizeof(trust)); - trust.objectSigningFlags |= CERTDB_USER; - - if( newSlot == PK11_GetInternalKeySlot() ) { - /* newcert is now a permanent cert */ - if( CERT_ChangeCertTrust(db, newcert, &trust) != SECSuccess) { - PR_fprintf(errorFD, - "Failed to change trust of generated certificate\n"); - errorCount++; - exit(ERRX); - } - } else { - if (CERT_AddTempCertToPerm (newcert, nickname, &trust) != SECSuccess) { - PR_fprintf(errorFD, "%s: Failure adding \"%s\" certificate to " - "permanent DB\n", PROGRAM_NAME, nickname); - errorCount++; - exit (ERRX); - } - } + PK11_FreeSlot(newSlot); if(verbosity >= 0){ PR_fprintf(outputFD, "certificate \"%s\" added to database\n", nickname); diff --git a/security/nss/cmd/signtool/util.c b/security/nss/cmd/signtool/util.c index 321fe6859..4b4febe28 100644 --- a/security/nss/cmd/signtool/util.c +++ b/security/nss/cmd/signtool/util.c @@ -285,6 +285,11 @@ VerifyCertDir(char *dir, char *keyName) { char fn [FNSIZE]; + /* don't try verifying if we don't have a local directory */ + if (strncmp(dir,"multiaccess:",sizeof("multiaccess:")-1) == 0) { + return; + } + sprintf (fn, "%s/cert7.db", dir); if (PR_Access (fn, PR_ACCESS_EXISTS)) @@ -804,8 +809,10 @@ InitCrypto(char *cert_dir, PRBool readOnly) NULL /*wincx*/) != SECSuccess) { fprintf(stderr, "%s: Unable to authenticate to %s.\n", PROGRAM_NAME, PK11_GetSlotName(slotinfo)); + PK11_FreeSlot(slotinfo); return -1; } + PK11_FreeSlot(slotinfo); } /* Make sure there is a password set on the internal key slot */ @@ -828,9 +835,11 @@ InitCrypto(char *cert_dir, PRBool readOnly) NULL /*wincx*/) != SECSuccess) { fprintf(stderr, "%s: Unable to authenticate to %s.\n", PROGRAM_NAME, PK11_GetSlotName(slotinfo)); + PK11_FreeSlot(slotinfo); return -1; } } + PK11_FreeSlot(slotinfo); } return 0; diff --git a/security/nss/cmd/smimetools/cmsutil.c b/security/nss/cmd/smimetools/cmsutil.c index 92263f1bb..ec2fe56e8 100644 --- a/security/nss/cmd/smimetools/cmsutil.c +++ b/security/nss/cmd/smimetools/cmsutil.c @@ -390,7 +390,7 @@ signed_data(struct signOptionsStr *signOptions) NSSCMSContentInfo *cinfo; NSSCMSSignedData *sigd; NSSCMSSignerInfo *signerinfo; - CERTCertificate *cert, *ekpcert; + CERTCertificate *cert= NULL, *ekpcert = NULL; if (cms_verbose) { fprintf(stderr, "Input to signed_data:\n"); @@ -563,8 +563,20 @@ signed_data(struct signOptionsStr *signOptions) if (cms_verbose) { fprintf(stderr, "created signed-date message\n"); } + if (ekpcert) { + CERT_DestroyCertificate(ekpcert); + } + if (cert) { + CERT_DestroyCertificate(cert); + } return cmsg; loser: + if (ekpcert) { + CERT_DestroyCertificate(ekpcert); + } + if (cert) { + CERT_DestroyCertificate(cert); + } NSS_CMSMessage_Destroy(cmsg); return NULL; } @@ -576,11 +588,11 @@ enveloped_data(struct envelopeOptionsStr *envelopeOptions) NSSCMSContentInfo *cinfo; NSSCMSEnvelopedData *envd; NSSCMSRecipientInfo *recipientinfo; - CERTCertificate **recipientcerts; + CERTCertificate **recipientcerts = NULL; CERTCertDBHandle *dbhandle; PLArenaPool *tmppoolp = NULL; SECOidTag bulkalgtag; - int keysize, i; + int keysize, i = 0; int cnt; dbhandle = envelopeOptions->options->certHandle; /* count the recipients */ @@ -607,10 +619,12 @@ enveloped_data(struct envelopeOptionsStr *envelopeOptions) == NULL) { SECU_PrintError(progName, "cannot find certificate for \"%s\"", envelopeOptions->recipients[i]); + i=0; goto loser; } } recipientcerts[i] = NULL; + i=0; /* find a nice bulk algorithm */ if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipientcerts, &bulkalgtag, &keysize) != SECSuccess) { @@ -661,11 +675,17 @@ enveloped_data(struct envelopeOptionsStr *envelopeOptions) fprintf(stderr, "ERROR: cannot add CMS recipientInfo object.\n"); goto loser; } + CERT_DestroyCertificate(recipientcerts[i]); } if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE); return cmsg; loser: + if (recipientcerts) { + for (; recipientcerts[i] != NULL; i++) { + CERT_DestroyCertificate(recipientcerts[i]); + } + } if (cmsg) NSS_CMSMessage_Destroy(cmsg); if (tmppoolp) @@ -829,10 +849,10 @@ signed_data_certsonly(struct certsonlyOptionsStr *certsonlyOptions) NSSCMSMessage *cmsg = NULL; NSSCMSContentInfo *cinfo; NSSCMSSignedData *sigd; - CERTCertificate **certs; + CERTCertificate **certs = NULL; CERTCertDBHandle *dbhandle; PLArenaPool *tmppoolp = NULL; - int i, cnt; + int i = 0, cnt; dbhandle = certsonlyOptions->options->certHandle; if ((cnt = nss_CMSArray_Count((void**)certsonlyOptions->recipients)) == 0) { fprintf(stderr, @@ -857,10 +877,12 @@ signed_data_certsonly(struct certsonlyOptionsStr *certsonlyOptions) == NULL) { SECU_PrintError(progName, "cannot find certificate for \"%s\"", certsonlyOptions->recipients[i]); + i=0; goto loser; } } certs[i] = NULL; + i=0; /* * create the message object */ @@ -877,12 +899,14 @@ signed_data_certsonly(struct certsonlyOptionsStr *certsonlyOptions) fprintf(stderr, "ERROR: cannot create CMS signedData object.\n"); goto loser; } + CERT_DestroyCertificate(certs[0]); for (i=1; i<cnt; i++) { if (NSS_CMSSignedData_AddCertChain(sigd, certs[i])) { fprintf(stderr, "ERROR: cannot add cert chain for \"%s\".\n", certsonlyOptions->recipients[i]); goto loser; } + CERT_DestroyCertificate(certs[i]); } cinfo = NSS_CMSMessage_GetContentInfo(cmsg); if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) @@ -900,6 +924,11 @@ signed_data_certsonly(struct certsonlyOptionsStr *certsonlyOptions) PORT_FreeArena(tmppoolp, PR_FALSE); return cmsg; loser: + if (certs) { + for (; i<cnt; i++) { + CERT_DestroyCertificate(certs[i]); + } + } if (cmsg) NSS_CMSMessage_Destroy(cmsg); if (tmppoolp) @@ -924,7 +953,7 @@ int main(int argc, char **argv) { FILE *outFile; - NSSCMSMessage *cmsg; + NSSCMSMessage *cmsg = NULL; PRFileDesc *inFile; PLOptState *optstate; PLOptStatus status; @@ -1299,6 +1328,10 @@ main(int argc, char **argv) SECU_PrintError(progName, "problem encrypting"); exitstatus = 1; } + if (encryptOptions.bulkkey) { + PK11_FreeSymKey(encryptOptions.bulkkey); + encryptOptions.bulkkey = NULL; + } break; case ENVELOPE: envelopeOptions.options = &options; @@ -1392,5 +1425,6 @@ main(int argc, char **argv) if (decodeOptions.contentFile) PR_Close(decodeOptions.contentFile); + NSS_Shutdown(); exit(exitstatus); } diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c index 29c90274e..461ba0641 100644 --- a/security/nss/cmd/strsclnt/strsclnt.c +++ b/security/nss/cmd/strsclnt/strsclnt.c @@ -39,8 +39,10 @@ #include <unistd.h> #endif #include <stdlib.h> +#if !defined(_WIN32_WCE) #include <errno.h> #include <fcntl.h> +#endif #include <stdarg.h> #include "plgetopt.h" @@ -293,6 +295,8 @@ printSecurityInfo(PRFileDesc *fd) fprintf(stderr, "strsclnt: issuer DN: %s\n", ip); PR_Free(ip); } + } + if (cert) { CERT_DestroyCertificate(cert); cert = NULL; } diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index f576b6af4..4598fdcc2 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -724,6 +724,7 @@ int main(int argc, char **argv) done: PR_Close(s); + SSL_ClearSessionCache(); NSS_Shutdown(); PR_Cleanup(); return error; diff --git a/security/nss/cmd/zlib/zutil.h b/security/nss/cmd/zlib/zutil.h index 12a59356c..6918260cf 100644 --- a/security/nss/cmd/zlib/zutil.h +++ b/security/nss/cmd/zlib/zutil.h @@ -15,7 +15,8 @@ #include "zlib.h" -#if defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS) +#if defined(_WIN32_WCE) +#elif defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS) # include <stddef.h> # include <errno.h> #else diff --git a/security/nss/lib/Makefile b/security/nss/lib/Makefile index 92aa6ff63..d7c687fe8 100644 --- a/security/nss/lib/Makefile +++ b/security/nss/lib/Makefile @@ -54,7 +54,9 @@ include $(CORE_DEPTH)/coreconf/config.mk # (4) Include "local" platform-dependent assignments (OPTIONAL). # ####################################################################### - +ifeq ($(OS_TARGET), WINCE) +DIRS := $(filter-out fortcrypt,$(DIRS)) +endif ####################################################################### # (5) Execute "global" rules. (OPTIONAL) # diff --git a/security/nss/lib/base/arena.c b/security/nss/lib/base/arena.c index 31bf5f485..648b7e864 100644 --- a/security/nss/lib/base/arena.c +++ b/security/nss/lib/base/arena.c @@ -1127,14 +1127,15 @@ nss_ZRealloc new_h = (struct pointer_header *)p; new_h->arena = h->arena; new_h->size = newSize; - rv = (void *)((char *)h + sizeof(struct pointer_header)); - (void)nsslibc_memcpy(rv, pointer, h->size); - (void)nsslibc_memset(&((char *)rv)[ h->size ], 0, - (newSize - h->size)); - (void)nsslibc_memset(pointer, 0, h->size); + rv = (void *)((char *)new_h + sizeof(struct pointer_header)); + if (rv != pointer) { + (void)nsslibc_memcpy(rv, pointer, h->size); + (void)nsslibc_memset(pointer, 0, h->size); + } + (void)nsslibc_memset(&((char *)rv)[ h->size ], 0, (newSize - h->size)); h->arena = (NSSArena *)NULL; h->size = 0; - PR_Unlock(h->arena->lock); + PR_Unlock(new_h->arena->lock); return rv; } /*NOTREACHED*/ diff --git a/security/nss/lib/base/base.h b/security/nss/lib/base/base.h index 492da7259..9a8d2d294 100644 --- a/security/nss/lib/base/base.h +++ b/security/nss/lib/base/base.h @@ -452,6 +452,25 @@ extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD; #define nss_ZNEWARRAY(arenaOpt, type, quantity) ((type *)nss_ZAlloc((arenaOpt), sizeof(type) * (quantity))) /* + * nss_ZREALLOCARRAY + * + * This preprocessor macro will reallocate memory for an array of + * new objects, and will cast the return value appropriately. + * This routine may return NULL upon error, in which case it will + * have set an error upon the error stack. + * + * The error may be one of the following values: + * NSS_ERROR_INVALID_POINTER + * NSS_ERROR_NO_MEMORY + * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD + * + * Return value: + * NULL upon error + * A pointer to the replacement segment of memory + */ +#define nss_ZREALLOCARRAY(p, type, quantity) ((type *)nss_ZRealloc((p), sizeof(type) * (quantity))) + +/* * nssArena_verifyPointer * * This method is only present in debug builds. diff --git a/security/nss/lib/base/list.c b/security/nss/lib/base/list.c index f4ef49b70..ae601d50c 100644 --- a/security/nss/lib/base/list.c +++ b/security/nss/lib/base/list.c @@ -313,19 +313,23 @@ nssList_Count(nssList *list) NSS_IMPLEMENT PRStatus nssList_GetArray(nssList *list, void **rvArray, PRUint32 maxElements) { - nssListIterator *iter; - void *el; + nssListElement *node; PRUint32 i = 0; PR_ASSERT(maxElements > 0); - iter = nssList_CreateIterator(list); - for (el = nssListIterator_Start(iter); el != NULL; - el = nssListIterator_Next(iter)) - { - rvArray[i++] = el; + node = list->head; + if (!node) { + return PR_SUCCESS; + } + NSSLIST_LOCK_IF(list); + while (node) { + rvArray[i++] = node->data; if (i == maxElements) break; + node = (nssListElement *)PR_NEXT_LINK(&node->link); + if (node == list->head) { + break; + } } - nssListIterator_Finish(iter); - nssListIterator_Destroy(iter); + NSSLIST_UNLOCK_IF(list); return PR_SUCCESS; } diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c index 983908737..89d351603 100644 --- a/security/nss/lib/certdb/certdb.c +++ b/security/nss/lib/certdb/certdb.c @@ -1659,6 +1659,7 @@ CERT_IsCADERCert(SECItem *derCert, unsigned int *type) { CERTCertificate *cert; PRBool isCA; + /* This is okay -- only looks at extensions */ cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return PR_FALSE; @@ -2006,6 +2007,7 @@ CERT_SaveImportedCert(CERTCertificate *cert, SECCertUsage usage, loser: rv = SECFailure; done: + return(rv); } @@ -2028,29 +2030,47 @@ 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_DecodeDERCertificate(derCerts[i], PR_FALSE, - NULL); + certs[fcerts] = CERT_NewTempCertificate(certdb, + derCerts[i], + NULL, + PR_FALSE, + PR_TRUE); if (certs[fcerts]) fcerts++; } if ( keepCerts ) { for ( i = 0; i < fcerts; i++ ) { + char* canickname = NULL; + PRBool freeNickname = PR_FALSE; + SECKEY_UpdateCertPQG(certs[i]); + + if ( CERT_IsCACert(certs[i], NULL) ) { + canickname = CERT_MakeCANickname(certs[i]); + if ( canickname != NULL ) { + freeNickname = PR_TRUE; + } + } + if(CERT_IsCACert(certs[i], NULL) && (fcerts > 1)) { /* if we are importing only a single cert and specifying * a nickname, we want to use that nickname if it a CA, * otherwise if there are more than one cert, we don't - * know which cert it belongs to. + * know which cert it belongs to. But we still may try + * the individual canickname from the cert itself. */ - rv = PK11_ImportCert(PK11_GetInternalKeySlot(),certs[i], - CK_INVALID_HANDLE,NULL,PR_TRUE); + rv = CERT_AddTempCertToPerm(certs[i], canickname, NULL); } else { - rv = PK11_ImportCert(PK11_GetInternalKeySlot(),certs[i], - CK_INVALID_HANDLE,nickname,PR_TRUE); + rv = CERT_AddTempCertToPerm(certs[i], + nickname?nickname:canickname, NULL); } if (rv == SECSuccess) { CERT_SaveImportedCert(certs[i], usage, caOnly, NULL); } + + if (PR_TRUE == freeNickname) { + PORT_Free(canickname); + } /* don't care if it fails - keep going */ } } diff --git a/security/nss/lib/certdb/certt.h b/security/nss/lib/certdb/certt.h index 1c5298383..3f70dcc84 100644 --- a/security/nss/lib/certdb/certt.h +++ b/security/nss/lib/certdb/certt.h @@ -177,7 +177,7 @@ struct CERTCertTrustStr { /* * defined the types of trust that exist */ -typedef enum { +typedef enum SECTrustTypeEnum { trustSSL = 0, trustEmail = 1, trustObjectSigning = 2, @@ -458,7 +458,7 @@ struct CERTDistNamesStr { NS_CERT_TYPE_EMAIL_CA | \ NS_CERT_TYPE_OBJECT_SIGNING_CA | \ EXT_KEY_USAGE_STATUS_RESPONDER ) -typedef enum { +typedef enum SECCertUsageEnum { certUsageSSLClient = 0, certUsageSSLServer = 1, certUsageSSLServerWithStepUp = 2, @@ -476,7 +476,7 @@ typedef enum { /* * Does the cert belong to the user, a peer, or a CA. */ -typedef enum { +typedef enum CERTCertOwnerEnum { certOwnerUser = 0, certOwnerPeer = 1, certOwnerCA = 2 @@ -485,7 +485,7 @@ typedef enum { /* * This enum represents the state of validity times of a certificate */ -typedef enum { +typedef enum SECCertTimeValidityEnum { secCertTimeValid = 0, secCertTimeExpired = 1, secCertTimeNotValidYet = 2 @@ -576,7 +576,7 @@ struct CERTBasicConstraintsStr { /* If we needed to extract the general name field, use this */ /* General Name types */ -typedef enum { +typedef enum CERTGeneralNameTypeEnum { certOtherName = 1, certRFC822Name = 2, certDNSName = 3, @@ -652,7 +652,7 @@ struct CERTAuthKeyIDStr { /* * defined the types of CRL Distribution points */ -typedef enum { +typedef enum DistributionPointTypesEnum { generalName = 1, /* only support this for now */ relativeDistinguishedName = 2 } DistributionPointTypes; @@ -734,7 +734,7 @@ typedef char * (*CERTDBNameFunc)(void *arg, int dbVersion); /* * types of cert packages that we can decode */ -typedef enum { +typedef enum CERTPackageTypeEnum { certPackageNone = 0, certPackageCert = 1, certPackagePKCS7 = 2, diff --git a/security/nss/lib/certdb/stanpcertdb.c b/security/nss/lib/certdb/stanpcertdb.c index 293b33d8a..654da08dd 100644 --- a/security/nss/lib/certdb/stanpcertdb.c +++ b/security/nss/lib/certdb/stanpcertdb.c @@ -86,8 +86,10 @@ SECStatus SEC_DeletePermCertificate(CERTCertificate *cert) { PRStatus nssrv; + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSCertificate *c = STAN_GetNSSCertificate(cert); nssrv = NSSCertificate_DeleteStoredObject(c, NULL); + nssTrustDomain_RemoveCertFromCache(td, c); return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; } @@ -135,17 +137,17 @@ SECStatus __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, CERTCertTrust *trust) { - PRStatus nssrv; NSSUTF8 *stanNick; PK11SlotInfo *slot; NSSToken *internal; NSSCryptoContext *context; + nssCryptokiObject *permInstance; NSSCertificate *c = STAN_GetNSSCertificate(cert); context = c->object.cryptoContext; if (!context) { - return PR_FAILURE; /* wasn't a temp cert */ + return SECFailure; /* wasn't a temp cert */ } - stanNick = NSSCertificate_GetNickname(c, NULL); + stanNick = nssCertificate_GetNickname(c, NULL); if (stanNick && nickname && strcmp(nickname, stanNick) != 0) { /* take the new nickname */ cert->nickname = NULL; @@ -157,20 +159,36 @@ __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, /* Delete the temp instance */ nssCertificateStore_Remove(context->certStore, c); c->object.cryptoContext = NULL; - /* the perm instance will assume the reference */ - nssList_Clear(c->object.instanceList, NULL); /* Import the perm instance onto the internal token */ slot = PK11_GetInternalKeySlot(); internal = PK11Slot_GetNSSToken(slot); - nssrv = nssToken_ImportCertificate(internal, NULL, c, stanNick, PR_TRUE); - if (nssrv != PR_SUCCESS) { + permInstance = nssToken_ImportCertificate(internal, NULL, + NSSCertificateType_PKIX, + &c->id, + stanNick, + &c->encoding, + &c->issuer, + &c->subject, + &c->serial, + cert->emailAddr, + PR_TRUE); + PK11_FreeSlot(slot); + if (!permInstance) { return SECFailure; } + nssPKIObject_AddInstance(&c->object, permInstance); + nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); /* reset the CERTCertificate fields */ cert->nssCertificate = NULL; cert = STAN_GetCERTCertificate(c); /* will return same pointer */ + if (!cert) { + return SECFailure; + } cert->istemp = PR_FALSE; cert->isperm = PR_TRUE; + if (!trust) { + return PR_SUCCESS; + } return (STAN_ChangeCertTrust(cert, trust) == PR_SUCCESS) ? SECSuccess: SECFailure; } @@ -188,11 +206,11 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, { PRStatus nssrv; NSSCertificate *c; - NSSCryptoContext *context; - NSSArena *arena; CERTCertificate *cc; NSSCertificate *tempCert; + nssPKIObject *pkio; NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); + NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); if (!isperm) { NSSDER encoding; NSSITEM_FROM_SECITEM(&encoding, derCert); @@ -208,27 +226,32 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, return STAN_GetCERTCertificate(c); } } - arena = NSSArena_Create(); - if (!arena) { + pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC); + if (!pkio) { return NULL; } - c = nss_ZNEW(arena, NSSCertificate); + c = nss_ZNEW(pkio->arena, NSSCertificate); if (!c) { - nssArena_Destroy(arena); + nssPKIObject_Destroy(pkio); return NULL; } - NSSITEM_FROM_SECITEM(&c->encoding, derCert); - nssrv = nssPKIObject_Initialize(&c->object, arena, NULL, NULL); - if (nssrv != PR_SUCCESS) { - goto loser; + c->object = *pkio; + if (copyDER) { + nssItem_Create(c->object.arena, &c->encoding, + derCert->len, derCert->data); + } else { + NSSITEM_FROM_SECITEM(&c->encoding, derCert); } /* Forces a decoding of the cert in order to obtain the parts used * below */ cc = STAN_GetCERTCertificate(c); - nssItem_Create(arena, + if (!cc) { + return NULL; + } + nssItem_Create(c->object.arena, &c->issuer, cc->derIssuer.len, cc->derIssuer.data); - nssItem_Create(arena, + nssItem_Create(c->object.arena, &c->subject, cc->derSubject.len, cc->derSubject.data); if (PR_TRUE) { /* CERTCertificate stores serial numbers decoded. I need the DER @@ -237,31 +260,30 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, SECItem derSerial = { 0 }; CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); if (!derSerial.data) goto loser; - nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data); + nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data); PORT_Free(derSerial.data); } if (nickname) { - c->object.tempName = nssUTF8_Create(arena, + c->object.tempName = nssUTF8_Create(c->object.arena, nssStringType_UTF8String, (NSSUTF8 *)nickname, PORT_Strlen(nickname)); } if (cc->emailAddr) { - c->email = nssUTF8_Create(arena, + c->email = nssUTF8_Create(c->object.arena, nssStringType_PrintableString, (NSSUTF8 *)cc->emailAddr, PORT_Strlen(cc->emailAddr)); } - context = STAN_GetDefaultCryptoContext(); /* this function cannot detect if the cert exists as a temp cert now, but * didn't when CERT_NewTemp was first called. */ - nssrv = NSSCryptoContext_ImportCertificate(context, c); + nssrv = NSSCryptoContext_ImportCertificate(gCC, c); if (nssrv != PR_SUCCESS) { goto loser; } /* so find the entry in the temp store */ - tempCert = NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(context, + tempCert = NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(gCC, &c->issuer, &c->serial); /* destroy the copy */ @@ -270,10 +292,12 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, /* and use the "official" entry */ c = tempCert; cc = STAN_GetCERTCertificate(c); + if (!cc) { + return NULL; + } } else { return NULL; } - c->object.trustDomain = STAN_GetDefaultTrustDomain(); cc->istemp = PR_TRUE; cc->isperm = PR_FALSE; return cc; @@ -308,17 +332,18 @@ CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndS static NSSCertificate * get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp) { - nssBestCertificateCB best; NSSUsage usage; - usage.anyUsage = PR_TRUE; - nssBestCertificate_SetArgs(&best, NULL, &usage, NULL); - if (ct) { - nssBestCertificate_Callback(ct, (void *)&best); - } - if (cp) { - nssBestCertificate_Callback(cp, (void *)&best); + NSSCertificate *arr[3]; + if (!ct) { + return nssCertificate_AddRef(cp); + } else if (!cp) { + return nssCertificate_AddRef(ct); } - return best.cert; + arr[0] = ct; + arr[1] = cp; + arr[2] = NULL; + usage.anyUsage = PR_TRUE; + return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL); } CERTCertificate * @@ -338,10 +363,16 @@ CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) c = get_best_temp_or_perm(ct, cp); if (ct) { CERTCertificate *cert = STAN_GetCERTCertificate(ct); + if (!cert) { + return NULL; + } CERT_DestroyCertificate(cert); } if (cp) { CERTCertificate *cert = STAN_GetCERTCertificate(cp); + if (!cert) { + return NULL; + } CERT_DestroyCertificate(cert); } if (c) { @@ -388,6 +419,9 @@ CERT_FindCertByNickname(CERTCertDBHandle *handle, char *nickname) CERT_DestroyCertificate(cert); if (ct) { CERTCertificate *cert2 = STAN_GetCERTCertificate(ct); + if (!cert2) { + return NULL; + } CERT_DestroyCertificate(cert2); } } else { @@ -438,6 +472,9 @@ CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, char *name) CERT_DestroyCertificate(cert); if (ct) { CERTCertificate *cert2 = STAN_GetCERTCertificate(ct); + if (!cert2) { + return NULL; + } CERT_DestroyCertificate(cert2); } } else { @@ -503,14 +540,18 @@ CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, ci = tSubjectCerts; while (ci && *ci) { cert = STAN_GetCERTCertificate(*ci); - add_to_subject_list(certList, cert, validOnly, sorttime); + if (cert) { + add_to_subject_list(certList, cert, validOnly, sorttime); + } ci++; } /* Iterate over the matching perm certs. Add them to the list */ ci = pSubjectCerts; while (ci && *ci) { cert = STAN_GetCERTCertificate(*ci); - add_to_subject_list(certList, cert, validOnly, sorttime); + if (cert) { + add_to_subject_list(certList, cert, validOnly, sorttime); + } ci++; } nss_ZFreeIf(tSubjectCerts); @@ -573,7 +614,9 @@ CERT_DestroyCertificate(CERTCertificate *cert) } /* delete the NSSCertificate */ NSSCertificate_Destroy(tmp); - } + } else { + PORT_FreeArena(cert->arena, PR_FALSE); + } #endif } return; @@ -825,6 +868,9 @@ loser: if (stanProfile) { nssSMIMEProfile_Destroy(stanProfile); } + if (slot) { + PK11_FreeSlot(slot); + } return(rv); } @@ -835,11 +881,12 @@ CERT_FindSMimeProfile(CERTCertificate *cert) PK11SlotInfo *slot = NULL; NSSCertificate *c; NSSCryptoContext *cc; + SECItem *rvItem = NULL; + c = STAN_GetNSSCertificate(cert); if (!c) return NULL; cc = c->object.cryptoContext; if (cc != NULL) { - SECItem *rvItem = NULL; nssSMIMEProfile *stanProfile; stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); if (stanProfile) { @@ -852,8 +899,12 @@ CERT_FindSMimeProfile(CERTCertificate *cert) } return rvItem; } - return + rvItem = PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL); + if (slot) { + PK11_FreeSlot(slot); + } + return rvItem; } /* diff --git a/security/nss/lib/certhigh/certhigh.c b/security/nss/lib/certhigh/certhigh.c index 06cccb43b..1cd3916ea 100644 --- a/security/nss/lib/certhigh/certhigh.c +++ b/security/nss/lib/certhigh/certhigh.c @@ -91,6 +91,31 @@ CERT_MatchNickname(char *name1, char *name2) { return PR_TRUE; } +static SECStatus +cert_UserCertsOnly(CERTCertList *certList) +{ + CERTCertListNode *node, *freenode; + CERTCertificate *cert; + + node = CERT_LIST_HEAD(certList); + + while ( ! CERT_LIST_END(node, certList) ) { + cert = node->cert; + if ( !( cert->trust->sslFlags & CERTDB_USER ) && + !( cert->trust->emailFlags & CERTDB_USER ) && + !( cert->trust->objectSigningFlags & CERTDB_USER ) ) { + /* Not a User Cert, so remove this cert from the list */ + freenode = node; + node = CERT_LIST_NEXT(node); + CERT_RemoveCertListNode(freenode); + } else { + /* Is a User cert, so leave it in the list */ + node = CERT_LIST_NEXT(node); + } + } + + return(SECSuccess); +} /* * Find all user certificates that match the given criteria. @@ -157,6 +182,8 @@ CERT_FindUserCertsByUsage(CERTCertDBHandle *handle, /* collect certs for this nickname, sorting them into the list */ certList = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, time, validOnly); + + cert_UserCertsOnly(certList); /* drop the extra reference */ CERT_DestroyCertificate(cert); @@ -287,6 +314,8 @@ CERT_FindUserCertByUsage(CERTCertDBHandle *handle, certList = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, time, validOnly); + cert_UserCertsOnly(certList); + /* drop the extra reference */ CERT_DestroyCertificate(cert); cert = NULL; @@ -825,6 +854,7 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool certs++; /* decode my certificate */ + /* This use is ok -- only looks at decoded parts, calls NewTemp later */ newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if ( newcert == NULL ) { goto loser; @@ -886,7 +916,8 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool } } - cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); + cert = CERT_NewTempCertificate(handle, derCert, NULL, + PR_FALSE, PR_FALSE); if ( cert == NULL ) { goto loser; } @@ -894,9 +925,7 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool /* get a default nickname for it */ nickname = CERT_MakeCANickname(cert); - cert->trust = &trust; - rv = PK11_ImportCert(PK11_GetInternalKeySlot(), cert, - CK_INVALID_HANDLE, nickname, PR_TRUE); + rv = CERT_AddTempCertToPerm(cert, nickname, &trust); /* free the nickname */ if ( nickname ) { @@ -1101,6 +1130,9 @@ loser: while (stanCert) { SECItem derCert; CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); + if (!cCert) { + goto loser; + } derCert.len = (unsigned int)stanCert->encoding.size; derCert.data = (unsigned char *)stanCert->encoding.data; SECITEM_CopyItem(arena, &chain->certs[i], &derCert); @@ -1121,7 +1153,9 @@ loser: stanCert = stanChain[i]; while (stanCert) { CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); - CERT_DestroyCertificate(cCert); + if (cCert) { + CERT_DestroyCertificate(cCert); + } stanCert = stanChain[++i]; } nss_ZFreeIf(stanChain); diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c index 4d4c549ac..6afa26b59 100644 --- a/security/nss/lib/certhigh/ocsp.c +++ b/security/nss/lib/certhigh/ocsp.c @@ -1490,6 +1490,9 @@ ocsp_GetResponseSignature(CERTOCSPResponse *response) ocspBasicOCSPResponse *basic; PORT_Assert(response != NULL); + if (NULL == response->responseBytes) { + return NULL; + } PORT_Assert(response->responseBytes != NULL); PORT_Assert(response->responseBytes->responseTypeTag == SEC_OID_PKIX_OCSP_BASIC_RESPONSE); @@ -1515,7 +1518,7 @@ CERT_DestroyOCSPResponse(CERTOCSPResponse *response) { if (response != NULL) { ocspSignature *signature = ocsp_GetResponseSignature(response); - if (signature->cert != NULL) + if (signature && signature->cert != NULL) CERT_DestroyCertificate(signature->cert); /* @@ -1853,7 +1856,8 @@ ocsp_GetEncodedResponse(PRArenaPool *arena, PRFileDesc *sock) bufsize = OCSP_BUFSIZE; - buf = PORT_Alloc(bufsize); + buf = PORT_Alloc(bufsize+1); + buf[bufsize] = 0; /* NULL termination so string functions are OK */ if (buf == NULL) { goto loser; } @@ -2015,26 +2019,6 @@ ocsp_GetEncodedResponse(PRArenaPool *arena, PRFileDesc *sock) continue; } /* - * So, we have a good newline pointer (just past a CR, LF or CRLF), - * but now we want to make sure that what it points to is long - * enough to be something we are looking for. If it isn't, add - * more to the buffer after first copying what's left to the - * beginning. - */ - if (((char *)bufEnd - newline) < 40) { - len = (char *)bufEnd - newline; - PORT_Memmove(buf, newline, len); - bytesRead = ocsp_MinMaxRead(sock, buf + len, 40 - len, - bufsize - len); - if (bytesRead <= 0) { - if (bytesRead == 0) - PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); - goto loser; - } - newline = (char *)buf; - bufEnd = buf + len + bytesRead; - } - /* * Okay, now we know that we are looking at an HTTP header line * with enough length to be safe for our comparisons. See if it is * one of the ones we are interested in. (That is, "Content-Length" diff --git a/security/nss/lib/ckfw/builtins/Makefile b/security/nss/lib/ckfw/builtins/Makefile index d58e910d9..7c392f2c9 100644 --- a/security/nss/lib/ckfw/builtins/Makefile +++ b/security/nss/lib/ckfw/builtins/Makefile @@ -47,8 +47,6 @@ ifeq (,$(filter-out WIN%,$(OS_TARGET))) EXTRA_LIBS += \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4_s.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4_s.lib \ - wsock32.lib \ - winmm.lib \ $(NULL) else diff --git a/security/nss/lib/ckfw/nsprstub.c b/security/nss/lib/ckfw/nsprstub.c index e4c33cdbd..c9e3964d9 100644 --- a/security/nss/lib/ckfw/nsprstub.c +++ b/security/nss/lib/ckfw/nsprstub.c @@ -200,7 +200,7 @@ PORT_ArenaUnmark(PLArenaPool *arena, void *mark) } char * -PORT_ArenaStrdup(PLArenaPool *arena,char *str) { +PORT_ArenaStrdup(PLArenaPool *arena,const char *str) { int len = PORT_Strlen(str)+1; char *newstr; diff --git a/security/nss/lib/ckfw/sessobj.c b/security/nss/lib/ckfw/sessobj.c index 11de006ba..66555fe23 100644 --- a/security/nss/lib/ckfw/sessobj.c +++ b/security/nss/lib/ckfw/sessobj.c @@ -202,7 +202,7 @@ nss_ckmdSessionObject_GetAttributeSize CK_RV *pError ); -static const NSSItem * +static NSSCKFWItem nss_ckmdSessionObject_GetAttribute ( NSSCKMDObject *mdObject, @@ -582,7 +582,7 @@ nss_ckmdSessionObject_GetAttributeSize * nss_ckmdSessionObject_GetAttribute * */ -static const NSSItem * +static NSSCKFWItem nss_ckmdSessionObject_GetAttribute ( NSSCKMDObject *mdObject, @@ -597,17 +597,20 @@ nss_ckmdSessionObject_GetAttribute CK_RV *pError ) { + NSSCKFWItem item; nssCKMDSessionObject *obj; CK_ULONG i; + item.needsFreeing = PR_FALSE; + item.item = NULL; #ifdef NSSDEBUG if( (CK_RV *)NULL == pError ) { - return 0; + return item; } *pError = nss_ckmdSessionObject_verifyPointer(mdObject); if( CKR_OK != *pError ) { - return 0; + return item; } /* We could even check all the other arguments, for sanity. */ @@ -617,12 +620,13 @@ nss_ckmdSessionObject_GetAttribute for( i = 0; i < obj->n; i++ ) { if( attribute == obj->types[i] ) { - return &obj->attributes[i]; + item.item = &obj->attributes[i]; + return item; } } *pError = CKR_ATTRIBUTE_TYPE_INVALID; - return 0; + return item; } /* diff --git a/security/nss/lib/crmf/asn1cmn.c b/security/nss/lib/crmf/asn1cmn.c index 59ce5b4a8..3ca062027 100644 --- a/security/nss/lib/crmf/asn1cmn.c +++ b/security/nss/lib/crmf/asn1cmn.c @@ -164,10 +164,7 @@ cmmf_DecodeDERCertificate(CERTCertDBHandle *db, SECItem *derCert) { CERTCertificate *newCert; - newCert = CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL); - if (newCert != NULL && newCert->dbhandle == NULL) { - newCert->dbhandle = db; - } + newCert = CERT_NewTempCertificate(db, derCert, NULL, PR_FALSE, PR_TRUE); return newCert; } diff --git a/security/nss/lib/crmf/respcmn.c b/security/nss/lib/crmf/respcmn.c index d7c703ec0..871ece3ec 100644 --- a/security/nss/lib/crmf/respcmn.c +++ b/security/nss/lib/crmf/respcmn.c @@ -168,7 +168,8 @@ cmmf_MakeCertList(CERTCertificate **inCerts) if (derCert->data == NULL) { derCert = freeCert = cmmf_encode_certificate(inCerts[i]); } - currCert=CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL); + currCert=CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + derCert, NULL, PR_FALSE, PR_TRUE); if (freeCert != NULL) { SECITEM_FreeItem(freeCert, PR_TRUE); freeCert = NULL; diff --git a/security/nss/lib/dev/Makefile b/security/nss/lib/dev/Makefile index 4cbbfed70..cd7561ce6 100644 --- a/security/nss/lib/dev/Makefile +++ b/security/nss/lib/dev/Makefile @@ -37,4 +37,17 @@ include $(CORE_DEPTH)/coreconf/config.mk include config.mk include $(CORE_DEPTH)/coreconf/rules.mk +# On AIX 4.3, IBM xlC_r compiler (version 3.6.6) cannot compile +# ckhelper.c in 64-bit mode for unknown reasons. A workaround is +# to compile it with optimizations turned on. (Bugzilla bug #63815) +ifeq ($(OS_TARGET)$(OS_RELEASE),AIX4.3) +ifeq ($(USE_64),1) +ifndef BUILD_OPT +$(OBJDIR)/ckhelper.o: ckhelper.c + @$(MAKE_OBJDIR) + $(CC) -o $@ -c -O2 $(CFLAGS) $< +endif +endif +endif + export:: private_export diff --git a/security/nss/lib/dev/ckhelper.c b/security/nss/lib/dev/ckhelper.c index 85283ff1f..1f3f1e3bc 100644 --- a/security/nss/lib/dev/ckhelper.c +++ b/security/nss/lib/dev/ckhelper.c @@ -35,26 +35,18 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ - -#ifdef NSS_3_4_CODE -#include "pkcs11.h" -#else #ifndef NSSCKEPV_H #include "nssckepv.h" #endif /* NSSCKEPV_H */ -#endif /* NSS_3_4_CODE */ + +#ifndef DEVM_H +#include "devm.h" +#endif /* DEVM_H */ #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ - static const CK_BBOOL s_true = CK_TRUE; NSS_IMPLEMENT_DATA const NSSItem g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) }; @@ -111,6 +103,7 @@ nssCKObject_GetAttributes CK_RV ckrv; PRStatus nssrv; PRBool alloced = PR_FALSE; + void *epv = nssSlot_GetCryptokiEPV(slot); hSession = session->handle; if (arenaOpt) { mark = nssArena_Mark(arenaOpt); @@ -124,8 +117,8 @@ nssCKObject_GetAttributes */ if (obj_template[0].ulValueLen == 0) { /* Get the storage size needed for each attribute */ - ckrv = CKAPI(slot)->C_GetAttributeValue(hSession, - object, obj_template, count); + ckrv = CKAPI(epv)->C_GetAttributeValue(hSession, + object, obj_template, count); if (ckrv != CKR_OK && ckrv != CKR_ATTRIBUTE_TYPE_INVALID && ckrv != CKR_ATTRIBUTE_SENSITIVE) @@ -154,8 +147,8 @@ nssCKObject_GetAttributes alloced = PR_TRUE; } /* Obtain the actual attribute values. */ - ckrv = CKAPI(slot)->C_GetAttributeValue(hSession, - object, obj_template, count); + ckrv = CKAPI(epv)->C_GetAttributeValue(hSession, + object, obj_template, count); nssSession_ExitMonitor(session); if (ckrv != CKR_OK && ckrv != CKR_ATTRIBUTE_TYPE_INVALID && @@ -177,7 +170,9 @@ nssCKObject_GetAttributes * of the attributes we passed. For those tokens read them one at * a time */ for (i=0; i < count; i++) { - if (obj_template[i].ulValueLen == 0) { + if ((obj_template[i].ulValueLen == 0) + || (obj_template[i].ulValueLen == -1)) { + obj_template[i].ulValueLen=0; (void) nssCKObject_GetAttributes(object,&obj_template[i], 1, arenaOpt, session, slot); } @@ -238,11 +233,12 @@ nssCKObject_IsAttributeTrue CK_ATTRIBUTE_PTR attr; CK_ATTRIBUTE atemplate = { 0, NULL, 0 }; CK_RV ckrv; + void *epv = nssSlot_GetCryptokiEPV(slot); attr = &atemplate; NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool); nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_GetAttributeValue(session->handle, object, - &atemplate, 1); + ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object, + &atemplate, 1); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { *rvStatus = PR_FAILURE; @@ -263,9 +259,10 @@ nssCKObject_SetAttributes ) { CK_RV ckrv; + void *epv = nssSlot_GetCryptokiEPV(slot); nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_SetAttributeValue(session->handle, object, - obj_template, count); + ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object, + obj_template, count); nssSession_ExitMonitor(session); if (ckrv == CKR_OK) { return PR_SUCCESS; @@ -290,3 +287,436 @@ nssCKObject_IsTokenObjectTemplate return PR_FALSE; } +static NSSCertificateType +nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib) +{ + CK_CERTIFICATE_TYPE ckCertType; + if (!attrib->pValue) { + /* default to PKIX */ + return NSSCertificateType_PKIX; + } + ckCertType = *((CK_ULONG *)attrib->pValue); + switch (ckCertType) { + case CKC_X_509: + return NSSCertificateType_PKIX; + default: + break; + } + return NSSCertificateType_Unknown; +} + +/* incoming pointers must be valid */ +NSS_IMPLEMENT PRStatus +nssCryptokiCertificate_GetAttributes +( + nssCryptokiObject *certObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSCertificateType *certTypeOpt, + NSSItem *idOpt, + NSSDER *encodingOpt, + NSSDER *issuerOpt, + NSSDER *serialOpt, + NSSDER *subjectOpt, + NSSASCII7 **emailOpt +) +{ + PRStatus status; + PRUint32 i; + nssSession *session; + NSSSlot *slot; + CK_ULONG template_size; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[7]; + /* Set up a template of all options chosen by caller */ + NSS_CK_TEMPLATE_START(cert_template, attr, template_size); + if (certTypeOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE); + } + if (idOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID); + } + if (encodingOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); + } + if (issuerOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER); + } + if (serialOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER); + } + if (subjectOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT); + } + if (emailOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_EMAIL); + } + NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size); + if (template_size == 0) { + /* caller didn't want anything */ + return PR_SUCCESS; + } + + status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt, + certObject, CKO_CERTIFICATE, + cert_template, template_size); + if (status != PR_SUCCESS) { + + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(certObject->token); + + slot = nssToken_GetSlot(certObject->token); + status = nssCKObject_GetAttributes(certObject->handle, + cert_template, template_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + } + + i=0; + if (certTypeOpt) { + *certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]); i++; + } + if (idOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt); i++; + } + if (encodingOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt); i++; + } + if (issuerOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt); i++; + } + if (serialOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt); i++; + } + if (subjectOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt); i++; + } + if (emailOpt) { + NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[i], *emailOpt); i++; + } + return PR_SUCCESS; +} + +#ifdef PURE_STAN_BUILD +static NSSKeyPairType +nss_key_pair_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib) +{ + CK_KEY_TYPE ckKeyType; + PR_ASSERT(attrib->pValue); + ckKeyType = *((CK_ULONG *)attrib->pValue); + switch (ckKeyType) { + case CKK_RSA: return NSSKeyPairType_RSA; + case CKK_DSA: return NSSKeyPairType_DSA; + default: break; + } + return NSSKeyPairType_Unknown; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiPrivateKey_GetAttributes +( + nssCryptokiObject *keyObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSKeyPairType *keyTypeOpt, + NSSItem *idOpt +) +{ + PRStatus status; + PRUint32 i; + nssSession *session; + NSSSlot *slot; + CK_ULONG template_size; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[2]; + /* Set up a template of all options chosen by caller */ + NSS_CK_TEMPLATE_START(key_template, attr, template_size); + if (keyTypeOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_KEY_TYPE); + } + if (idOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID); + } + NSS_CK_TEMPLATE_FINISH(key_template, attr, template_size); + if (template_size == 0) { + /* caller didn't want anything */ + return PR_SUCCESS; + } + + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(keyObject->token); + + slot = nssToken_GetSlot(keyObject->token); + status = nssCKObject_GetAttributes(keyObject->handle, + key_template, template_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + + i=0; + if (keyTypeOpt) { + *keyTypeOpt = nss_key_pair_type_from_ck_attrib(&key_template[i]); i++; + } + if (idOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&key_template[i], idOpt); i++; + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiPublicKey_GetAttributes +( + nssCryptokiObject *keyObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSKeyPairType *keyTypeOpt, + NSSItem *idOpt +) +{ + PRStatus status; + PRUint32 i; + nssSession *session; + NSSSlot *slot; + CK_ULONG template_size; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[2]; + /* Set up a template of all options chosen by caller */ + NSS_CK_TEMPLATE_START(key_template, attr, template_size); + if (keyTypeOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_KEY_TYPE); + } + if (idOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID); + } + NSS_CK_TEMPLATE_FINISH(key_template, attr, template_size); + if (template_size == 0) { + /* caller didn't want anything */ + return PR_SUCCESS; + } + + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(keyObject->token); + + slot = nssToken_GetSlot(keyObject->token); + status = nssCKObject_GetAttributes(keyObject->handle, + key_template, template_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + + i=0; + if (keyTypeOpt) { + *keyTypeOpt = nss_key_pair_type_from_ck_attrib(&key_template[i]); i++; + } + if (idOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&key_template[i], idOpt); i++; + } + return PR_SUCCESS; +} +#endif /* PURE_STAN_BUILD */ + +static nssTrustLevel +get_nss_trust +( + CK_TRUST ckt +) +{ + nssTrustLevel t; + switch (ckt) { + case CKT_NETSCAPE_UNTRUSTED: t = nssTrustLevel_NotTrusted; break; + case CKT_NETSCAPE_TRUSTED_DELEGATOR: t = nssTrustLevel_TrustedDelegator; + break; + case CKT_NETSCAPE_VALID_DELEGATOR: t = nssTrustLevel_ValidDelegator; break; + case CKT_NETSCAPE_TRUSTED: t = nssTrustLevel_Trusted; break; + case CKT_NETSCAPE_VALID: t = nssTrustLevel_Valid; break; + case CKT_NETSCAPE_MUST_VERIFY: + case CKT_NETSCAPE_TRUST_UNKNOWN: + default: + t = nssTrustLevel_Unknown; break; + } + return t; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiTrust_GetAttributes +( + nssCryptokiObject *trustObject, + nssSession *sessionOpt, + nssTrustLevel *serverAuth, + nssTrustLevel *clientAuth, + nssTrustLevel *codeSigning, + nssTrustLevel *emailProtection +) +{ + PRStatus status; + NSSSlot *slot; + nssSession *session; + CK_BBOOL isToken; + CK_TRUST saTrust, caTrust, epTrust, csTrust; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE trust_template[5]; + CK_ULONG trust_size; + + /* Use the trust object to find the trust settings */ + NSS_CK_TEMPLATE_START(trust_template, attr, trust_size); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust); + NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size); + + status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL, + trustObject, + CKO_NETSCAPE_TRUST, + trust_template, trust_size); + if (status != PR_SUCCESS) { + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(trustObject->token); + + slot = nssToken_GetSlot(trustObject->token); + status = nssCKObject_GetAttributes(trustObject->handle, + trust_template, trust_size, + NULL, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + } + + *serverAuth = get_nss_trust(saTrust); + *clientAuth = get_nss_trust(caTrust); + *emailProtection = get_nss_trust(epTrust); + *codeSigning = get_nss_trust(csTrust); + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiCRL_GetAttributes +( + nssCryptokiObject *crlObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSItem *encodingOpt, + NSSUTF8 **urlOpt, + PRBool *isKRLOpt +) +{ + PRStatus status; + NSSSlot *slot; + nssSession *session; + CK_BBOOL isToken; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE crl_template[5]; + CK_ULONG crl_size; + PRUint32 i; + + NSS_CK_TEMPLATE_START(crl_template, attr, crl_size); + /* NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); */ + if (encodingOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); + } + if (urlOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_URL); + } + if (isKRLOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_KRL); + } + NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size); + + status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL, + crlObject, + CKO_NETSCAPE_CRL, + crl_template, crl_size); + if (status != PR_SUCCESS) { + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(crlObject->token); + + slot = nssToken_GetSlot(crlObject->token); + status = nssCKObject_GetAttributes(crlObject->handle, + crl_template, crl_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + } + + i=0; + if (encodingOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); i++; + } + if (urlOpt) { + NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt); i++; + } + if (isKRLOpt) { + NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); i++; + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiPrivateKey_SetCertificate +( + nssCryptokiObject *keyObject, + nssSession *sessionOpt, + NSSUTF8 *nickname, + NSSItem *id, + NSSDER *subject +) +{ + CK_RV ckrv; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[3]; + CK_ULONG key_size; + void *epv = nssToken_GetCryptokiEPV(keyObject->token); + nssSession *session; + NSSToken *token = keyObject->token; + nssSession *defaultSession = nssToken_GetDefaultSession(token); + PRBool createdSession = PR_FALSE; + + NSS_CK_TEMPLATE_START(key_template, attr, key_size); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size); + + if (sessionOpt) { + if (!nssSession_IsReadWrite(sessionOpt)) { + return PR_FAILURE; + } else { + session = sessionOpt; + } + } else if (nssSession_IsReadWrite(defaultSession)) { + session = defaultSession; + } else { + NSSSlot *slot = nssToken_GetSlot(token); + session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); + createdSession = PR_TRUE; + nssSlot_Destroy(slot); + } + + ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, + keyObject->handle, + key_template, + key_size); + + if (createdSession) { + nssSession_Destroy(session); + } + + return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; +} + diff --git a/security/nss/lib/dev/ckhelper.h b/security/nss/lib/dev/ckhelper.h index 1d92eec0e..9beab920d 100644 --- a/security/nss/lib/dev/ckhelper.h +++ b/security/nss/lib/dev/ckhelper.h @@ -50,10 +50,6 @@ static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; PR_BEGIN_EXTERN_C -/* Shortcut to cryptoki API functions. */ -#define CKAPI(x) \ - ((CK_FUNCTION_LIST_PTR)((x)->epv)) - /* Some globals to keep from constantly redeclaring common cryptoki * attribute types on the stack. */ @@ -90,6 +86,12 @@ NSS_EXTERN_DATA const NSSItem g_ck_class_privkey; (pattr)->ulValueLen = (CK_ULONG)sizeof(var); \ (pattr)++; +#define NSS_CK_SET_ATTRIBUTE_NULL(pattr, kind) \ + (pattr)->type = kind; \ + (pattr)->pValue = (CK_VOID_PTR)NULL; \ + (pattr)->ulValueLen = 0; \ + (pattr)++; + #define NSS_CK_TEMPLATE_FINISH(_template, attr, size) \ size = (attr) - (_template); \ PR_ASSERT(size <= sizeof(_template)/sizeof(_template[0])); @@ -107,6 +109,15 @@ NSS_EXTERN_DATA const NSSItem g_ck_class_privkey; (item)->size = 0; \ } +#define NSS_CK_ATTRIBUTE_TO_BOOL(attrib, boolvar) \ + if ((attrib)->ulValueLen > 0) { \ + if (*((CK_BBOOL*)(attrib)->pValue) == CK_TRUE) { \ + boolvar = PR_TRUE; \ + } else { \ + boolvar = PR_FALSE; \ + } \ + } + /* NSS_CK_ATTRIBUTE_TO_UTF8(attrib, str) * * Convert a CK_ATTRIBUTE to a string. @@ -131,7 +142,7 @@ nssCKObject_GetAttributes CK_ULONG count, NSSArena *arenaOpt, nssSession *session, - NSSSlot *slot + NSSSlot *slot ); /* Get a single attribute as an item. */ diff --git a/security/nss/lib/dev/dev.h b/security/nss/lib/dev/dev.h index 65dee8d63..e7651aa47 100644 --- a/security/nss/lib/dev/dev.h +++ b/security/nss/lib/dev/dev.h @@ -34,53 +34,142 @@ #ifndef DEV_H #define DEV_H +/* + * dev.h + * + * Low-level methods for interaction with cryptoki devices + */ + #ifdef DEBUG static const char DEV_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef DEVT_H -#include "devt.h" -#endif /* DEVT_H */ - #ifndef NSSCKT_H #include "nssckt.h" #endif /* NSSCKT_H */ -#ifndef NSSPKIT_H -#include "nsspkit.h" -#endif /* NSSPKIT_H */ +#ifndef NSSDEV_H +#include "nssdev.h" +#endif /* NSSDEV_H */ -#ifndef BASET_H -#include "baset.h" -#endif /* BASET_H */ +#ifndef DEVT_H +#include "devt.h" +#endif /* DEVT_H */ -/* - * nssdev.h +PR_BEGIN_EXTERN_C + +/* the global module list + * + * These functions are for managing the global set of modules. Trust Domains, + * etc., will draw from this set. These functions are completely internal + * and only invoked when there are changes to the global module state + * (load or unload). * - * This file prototypes the methods of the low-level cryptoki devices. + * nss_InitializeGlobalModuleList + * nss_DestroyGlobalModuleList + * nss_GetLoadedModules * - * |-----------|---> NSSSlot <--> NSSToken - * | NSSModule |---> NSSSlot <--> NSSToken - * |-----------|---> NSSSlot <--> NSSToken + * nssGlobalModuleList_Add + * nssGlobalModuleList_Remove + * nssGlobalModuleList_FindModuleByName + * nssGlobalModuleList_FindSlotByName + * nssGlobalModuleList_FindTokenByName */ -PR_BEGIN_EXTERN_C +NSS_EXTERN PRStatus +nss_InitializeGlobalModuleList +( + void +); + +NSS_EXTERN PRStatus +nss_DestroyGlobalModuleList +( + void +); + +NSS_EXTERN NSSModule ** +nss_GetLoadedModules +( + void +); + +NSS_EXTERN PRStatus +nssGlobalModuleList_Add +( + NSSModule *module +); + +NSS_EXTERN PRStatus +nssGlobalModuleList_Remove +( + NSSModule *module +); + +NSS_EXTERN NSSModule * +nssGlobalModuleList_FindModuleByName +( + NSSUTF8 *moduleName +); + +NSS_EXTERN NSSSlot * +nssGlobalModuleList_FindSlotByName +( + NSSUTF8 *slotName +); + +NSS_EXTERN NSSToken * +nssGlobalModuleList_FindTokenByName +( + NSSUTF8 *tokenName +); + +NSS_EXTERN NSSToken * +nss_GetDefaultCryptoToken +( + void +); + +NSS_EXTERN NSSToken * +nss_GetDefaultDatabaseToken +( + void +); + +/* + * |-----------|<---> NSSSlot <--> NSSToken + * | NSSModule |<---> NSSSlot <--> NSSToken + * |-----------|<---> NSSSlot <--> NSSToken + */ + +/* NSSModule + * + * nssModule_Create + * nssModule_CreateFromSpec + * nssModule_AddRef + * nssModule_GetName + * nssModule_GetSlots + * nssModule_FindSlotByName + * nssModule_FindTokenByName + * nssModule_GetCertOrder + */ NSS_EXTERN NSSModule * nssModule_Create ( NSSUTF8 *moduleOpt, NSSUTF8 *uriOpt, - NSSUTF8 *opaqueOpt, /* XXX is this where the mech flags go??? */ + NSSUTF8 *opaqueOpt, void *reserved - /* XXX more? */ ); /* This is to use the new loading mechanism. */ NSS_EXTERN NSSModule * nssModule_CreateFromSpec ( - NSSUTF8 *moduleSpec + NSSUTF8 *moduleSpec, + NSSModule *parent, + PRBool loadSubModules ); NSS_EXTERN PRStatus @@ -95,20 +184,8 @@ nssModule_AddRef NSSModule *mod ); -NSS_EXTERN PRStatus -nssModule_Load -( - NSSModule *mod -); - -NSS_EXTERN PRStatus -nssModule_Unload -( - NSSModule *mod -); - -NSS_EXTERN PRStatus -nssModule_LogoutAllSlots +NSS_EXTERN NSSUTF8 * +nssModule_GetName ( NSSModule *mod ); @@ -133,27 +210,69 @@ nssModule_FindTokenByName NSSUTF8 *tokenName ); -/* This descends from NSSTrustDomain_TraverseCertificates, a questionable - * function. Do we want NSS to have access to this at the module level? +NSS_EXTERN PRInt32 +nssModule_GetCertOrder +( + NSSModule *module +); + +/* NSSSlot + * + * nssSlot_Destroy + * nssSlot_AddRef + * nssSlot_GetName + * nssSlot_GetTokenName + * nssSlot_IsTokenPresent + * nssSlot_IsPermanent + * nssSlot_IsFriendly + * nssSlot_IsHardware + * nssSlot_Refresh + * nssSlot_GetModule + * nssSlot_GetToken + * nssSlot_Login + * nssSlot_Logout + * nssSlot_SetPassword + * nssSlot_CreateSession */ -NSS_EXTERN PRStatus * -nssModule_TraverseCertificates + +NSS_EXTERN PRStatus +nssSlot_Destroy ( - NSSModule *mod, - PRStatus (*callback)(NSSCertificate *c, void *arg), - void *arg + NSSSlot *slot ); NSS_EXTERN NSSSlot * -nssSlot_Create +nssSlot_AddRef ( - NSSArena *arenaOpt, - CK_SLOT_ID slotId, - NSSModule *parent + NSSSlot *slot ); -NSS_EXTERN PRStatus -nssSlot_Destroy +NSS_EXTERN NSSUTF8 * +nssSlot_GetName +( + NSSSlot *slot +); + +NSS_EXTERN NSSUTF8 * +nssSlot_GetTokenName +( + NSSSlot *slot +); + +NSS_EXTERN NSSModule * +nssSlot_GetModule +( + NSSSlot *slot +); + +NSS_EXTERN NSSToken * +nssSlot_GetToken +( + NSSSlot *slot +); + +NSS_EXTERN PRBool +nssSlot_IsTokenPresent ( NSSSlot *slot ); @@ -164,30 +283,34 @@ nssSlot_IsPermanent NSSSlot *slot ); -NSS_EXTERN PRStatus -nssSlot_Refresh +NSS_EXTERN PRBool +nssSlot_IsFriendly ( NSSSlot *slot ); -NSS_EXTERN NSSSlot * -nssSlot_AddRef +NSS_EXTERN PRBool +nssSlot_IsHardware ( NSSSlot *slot ); -NSS_EXTERN NSSUTF8 * -nssSlot_GetName +NSS_EXTERN PRBool +nssSlot_IsLoggedIn ( - NSSSlot *slot, - NSSArena *arenaOpt + NSSSlot *slot +); + +NSS_EXTERN PRStatus +nssSlot_Refresh +( + NSSSlot *slot ); NSS_EXTERN PRStatus nssSlot_Login ( NSSSlot *slot, - PRBool asSO, NSSCallback *pwcb ); extern const NSSError NSS_ERROR_INVALID_PASSWORD; @@ -213,7 +336,8 @@ NSS_EXTERN PRStatus nssSlot_SetPassword ( NSSSlot *slot, - NSSCallback *pwcb + NSSUTF8 *oldPasswordOpt, + NSSUTF8 *newPassword ); extern const NSSError NSS_ERROR_INVALID_PASSWORD; extern const NSSError NSS_ERROR_USER_CANCELED; @@ -230,13 +354,37 @@ nssSlot_CreateSession PRBool readWrite /* so far, this is the only flag used */ ); -NSS_EXTERN NSSToken * -nssToken_Create -( - NSSArena *arenaOpt, - CK_SLOT_ID slotID, - NSSSlot *parent -); +/* NSSToken + * + * nssToken_Destroy + * nssToken_AddRef + * nssToken_GetName + * nssToken_GetModule + * nssToken_GetSlot + * nssToken_NeedsPINInitialization + * nssToken_ImportCertificate + * nssToken_ImportTrust + * nssToken_ImportCRL + * nssToken_GenerateKeyPair + * nssToken_GenerateSymmetricKey + * nssToken_DeleteStoredObject + * nssToken_FindCertificates + * nssToken_FindCertificatesBySubject + * nssToken_FindCertificatesByNickname + * nssToken_FindCertificatesByEmail + * nssToken_FindCertificateByIssuerAndSerialNumber + * nssToken_FindCertificateByEncodedCertificate + * nssToken_FindTrustObjects + * nssToken_FindTrustForCertificate + * nssToken_FindCRLs + * nssToken_FindCRLsBySubject + * nssToken_FindPrivateKeys + * nssToken_FindPrivateKeyByID + * nssToken_Digest + * nssToken_BeginDigest + * nssToken_ContinueDigest + * nssToken_FinishDigest + */ NSS_EXTERN PRStatus nssToken_Destroy @@ -244,12 +392,6 @@ nssToken_Destroy NSSToken *tok ); -NSS_EXTERN PRBool -nssToken_IsPresent -( - NSSToken *token -); - NSS_EXTERN NSSToken * nssToken_AddRef ( @@ -262,142 +404,215 @@ nssToken_GetName NSSToken *tok ); -NSS_EXTERN PRStatus +NSS_EXTERN NSSModule * +nssToken_GetModule +( + NSSToken *token +); + +NSS_EXTERN NSSSlot * +nssToken_GetSlot +( + NSSToken *tok +); + +NSS_EXTERN PRBool +nssToken_NeedsPINInitialization +( + NSSToken *token +); + +NSS_EXTERN nssCryptokiObject * nssToken_ImportCertificate ( NSSToken *tok, nssSession *sessionOpt, - NSSCertificate *cert, + NSSCertificateType certType, + NSSItem *id, NSSUTF8 *nickname, + NSSDER *encoding, + NSSDER *issuer, + NSSDER *subject, + NSSDER *serial, + NSSASCII7 *emailAddr, PRBool asTokenObject ); - -NSS_EXTERN PRStatus + +NSS_EXTERN nssCryptokiObject * nssToken_ImportTrust ( NSSToken *tok, nssSession *sessionOpt, - NSSTrust *trust, + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTrustLevel serverAuth, + nssTrustLevel clientAuth, + nssTrustLevel codeSigning, + nssTrustLevel emailProtection, PRBool asTokenObject ); -NSS_EXTERN PRStatus -nssToken_SetTrustCache +NSS_EXTERN nssCryptokiObject * +nssToken_ImportCRL ( - NSSToken *tok + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + NSSDER *encoding, + PRBool isKRL, + NSSUTF8 *url, + PRBool asTokenObject ); +/* Permanently remove an object from the token. */ NSS_EXTERN PRStatus -nssToken_SetCrlCache +nssToken_DeleteStoredObject ( - NSSToken *tok + nssCryptokiObject *instance ); -NSS_EXTERN PRBool -nssToken_HasCrls +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificates ( - NSSToken *tok + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN PRStatus -nssToken_SetHasCrls +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesBySubject ( - NSSToken *tok + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN NSSPublicKey * -nssToken_GenerateKeyPair +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesByNickname ( - NSSToken *tok, - nssSession *sessionOpt - /* algorithm and parameters */ + NSSToken *token, + nssSession *sessionOpt, + NSSUTF8 *name, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN NSSSymmetricKey * -nssToken_GenerateSymmetricKey +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesByEmail ( - NSSToken *tok, - nssSession *sessionOpt - /* algorithm and parameters */ + NSSToken *token, + nssSession *sessionOpt, + NSSASCII7 *email, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -/* Permanently remove an object from the token. */ -NSS_EXTERN PRStatus -nssToken_DeleteStoredObject +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesByID ( - nssCryptokiInstance *instance + NSSToken *token, + nssSession *sessionOpt, + NSSItem *id, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN NSSTrust * -nssToken_FindTrustForCert +NSS_EXTERN nssCryptokiObject * +nssToken_FindCertificateByIssuerAndSerialNumber ( NSSToken *token, nssSession *sessionOpt, - NSSCertificate *c, - nssTokenSearchType searchType + NSSDER *issuer, + NSSDER *serial, + nssTokenSearchType searchType, + PRStatus *statusOpt ); -NSS_EXTERN PRStatus -nssToken_TraverseCertificates +NSS_EXTERN nssCryptokiObject * +nssToken_FindCertificateByEncodedCertificate ( - NSSToken *tok, + NSSToken *token, nssSession *sessionOpt, - nssTokenCertSearch *search + NSSBER *encodedCertificate, + nssTokenSearchType searchType, + PRStatus *statusOpt ); -NSS_EXTERN PRStatus -nssToken_TraverseCertificatesBySubject +NSS_EXTERN nssCryptokiObject ** +nssToken_FindTrustObjects ( NSSToken *token, nssSession *sessionOpt, - NSSDER *subject, - nssTokenCertSearch *search + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN PRStatus -nssToken_TraverseCertificatesByNickname +NSS_EXTERN nssCryptokiObject * +nssToken_FindTrustForCertificate ( NSSToken *token, nssSession *sessionOpt, - NSSUTF8 *name, - nssTokenCertSearch *search + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTokenSearchType searchType ); -NSS_EXTERN PRStatus -nssToken_TraverseCertificatesByEmail +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCRLs ( NSSToken *token, nssSession *sessionOpt, - NSSASCII7 *email, - nssTokenCertSearch *search + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN NSSCertificate * -nssToken_FindCertificateByIssuerAndSerialNumber +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCRLsBySubject ( NSSToken *token, nssSession *sessionOpt, - NSSDER *issuer, - NSSDER *serial, - nssTokenSearchType searchType + NSSDER *subject, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN NSSCertificate * -nssToken_FindCertificateByEncodedCertificate +NSS_EXTERN nssCryptokiObject ** +nssToken_FindPrivateKeys ( NSSToken *token, nssSession *sessionOpt, - NSSBER *encodedCertificate, - nssTokenSearchType searchType + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ); -NSS_EXTERN NSSTrust * -nssToken_FindTrustForCert +NSS_EXTERN nssCryptokiObject * +nssToken_FindPrivateKeyByID ( NSSToken *token, - nssSession *session, - NSSCertificate *c, - nssTokenSearchType searchType + nssSession *sessionOpt, + NSSItem *keyID +); + +NSS_EXTERN nssCryptokiObject * +nssToken_FindPublicKeyByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *keyID ); NSS_EXTERN NSSItem * @@ -436,6 +651,14 @@ nssToken_FinishDigest NSSArena *arenaOpt ); +/* nssSession + * + * nssSession_Destroy + * nssSession_EnterMonitor + * nssSession_ExitMonitor + * nssSession_IsReadWrite + */ + NSS_EXTERN PRStatus nssSession_Destroy ( @@ -463,28 +686,283 @@ nssSession_IsReadWrite nssSession *s ); -NSS_EXTERN NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateSHA1Digest +/* nssCryptokiObject + * + * An object living on a cryptoki token. + * Not really proper to mix up the object types just because + * nssCryptokiObject itself is generic, but doing so anyway. + * + * nssCryptokiObject_Destroy + * nssCryptokiObject_Equal + * nssCryptokiObject_Clone + * nssCryptokiCertificate_GetAttributes + * nssCryptokiPrivateKey_GetAttributes + * nssCryptokiPublicKey_GetAttributes + * nssCryptokiTrust_GetAttributes + * nssCryptokiCRL_GetAttributes + */ + +NSS_EXTERN void +nssCryptokiObject_Destroy ( - NSSArena *arenaOpt + nssCryptokiObject *object ); -NSS_EXTERN NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateMD5Digest +NSS_EXTERN PRBool +nssCryptokiObject_Equal +( + nssCryptokiObject *object1, + nssCryptokiObject *object2 +); + +NSS_EXTERN nssCryptokiObject * +nssCryptokiObject_Clone +( + nssCryptokiObject *object +); + +NSS_EXTERN PRStatus +nssCryptokiCertificate_GetAttributes +( + nssCryptokiObject *object, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSCertificateType *certTypeOpt, + NSSItem *idOpt, + NSSDER *encodingOpt, + NSSDER *issuerOpt, + NSSDER *serialOpt, + NSSDER *subjectOpt, + NSSASCII7 **emailOpt +); + +NSS_EXTERN PRStatus +nssCryptokiTrust_GetAttributes +( + nssCryptokiObject *trustObject, + nssSession *sessionOpt, + nssTrustLevel *serverAuth, + nssTrustLevel *clientAuth, + nssTrustLevel *codeSigning, + nssTrustLevel *emailProtection +); + +NSS_EXTERN PRStatus +nssCryptokiCRL_GetAttributes +( + nssCryptokiObject *crlObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSItem *encodingOpt, + NSSUTF8 **urlOpt, + PRBool *isKRLOpt +); + +/* I'm including this to handle import of certificates in NSS 3.5. This + * function will set the cert-related attributes of a key, in order to + * associate it with a cert. Does it stay like this for 4.0? + */ +NSS_EXTERN PRStatus +nssCryptokiPrivateKey_SetCertificate +( + nssCryptokiObject *keyObject, + nssSession *sessionOpt, + NSSUTF8 *nickname, + NSSItem *id, + NSSDER *subject +); + +NSS_EXTERN void +nssModuleArray_Destroy +( + NSSModule **modules +); + +/* nssSlotArray + * + * nssSlotArray_Destroy + */ + +NSS_EXTERN void +nssSlotArray_Destroy +( + NSSSlot **slots +); + +/* nssTokenArray + * + * nssTokenArray_Destroy + */ + +NSS_EXTERN void +nssTokenArray_Destroy +( + NSSToken **tokens +); + +/* nssCryptokiObjectArray + * + * nssCryptokiObjectArray_Destroy + */ +NSS_EXTERN void +nssCryptokiObjectArray_Destroy +( + nssCryptokiObject **object +); + +/* nssSlotList +* + * An ordered list of slots. The order can be anything, it is set in the + * Add methods. Perhaps it should be CreateInCertOrder, ...? + * + * nssSlotList_Create + * nssSlotList_Destroy + * nssSlotList_Add + * nssSlotList_AddModuleSlots + * nssSlotList_GetSlots + * nssSlotList_FindSlotByName + * nssSlotList_FindTokenByName + * nssSlotList_GetBestSlot + * nssSlotList_GetBestSlotForAlgorithmAndParameters + * nssSlotList_GetBestSlotForAlgorithmsAndParameters + */ + +/* nssSlotList_Create + */ +NSS_EXTERN nssSlotList * +nssSlotList_Create ( NSSArena *arenaOpt ); +/* nssSlotList_Destroy + */ +NSS_EXTERN void +nssSlotList_Destroy +( + nssSlotList *slotList +); + +/* nssSlotList_Add + * + * Add the given slot in the given order. + */ +NSS_EXTERN PRStatus +nssSlotList_Add +( + nssSlotList *slotList, + NSSSlot *slot, + PRUint32 order +); + +/* nssSlotList_AddModuleSlots + * + * Add all slots in the module, in the given order (the slots will have + * equal weight). + */ +NSS_EXTERN PRStatus +nssSlotList_AddModuleSlots +( + nssSlotList *slotList, + NSSModule *module, + PRUint32 order +); + +/* nssSlotList_GetSlots + */ +NSS_EXTERN NSSSlot ** +nssSlotList_GetSlots +( + nssSlotList *slotList +); + +/* nssSlotList_FindSlotByName + */ +NSS_EXTERN NSSSlot * +nssSlotList_FindSlotByName +( + nssSlotList *slotList, + NSSUTF8 *slotName +); + +/* nssSlotList_FindTokenByName + */ +NSS_EXTERN NSSToken * +nssSlotList_FindTokenByName +( + nssSlotList *slotList, + NSSUTF8 *tokenName +); + +/* nssSlotList_GetBestSlot + * + * The best slot is the highest ranking in order, i.e., the first in the + * list. + */ +NSS_EXTERN NSSSlot * +nssSlotList_GetBestSlot +( + nssSlotList *slotList +); + +/* nssSlotList_GetBestSlotForAlgorithmAndParameters + * + * Highest-ranking slot than can handle algorithm/parameters. + */ +NSS_EXTERN NSSSlot * +nssSlotList_GetBestSlotForAlgorithmAndParameters +( + nssSlotList *slotList, + NSSAlgorithmAndParameters *ap +); + +/* nssSlotList_GetBestSlotForAlgorithmsAndParameters + * + * Highest-ranking slot than can handle all algorithms/parameters. + */ +NSS_EXTERN NSSSlot * +nssSlotList_GetBestSlotForAlgorithmsAndParameters +( + nssSlotList *slotList, + NSSAlgorithmAndParameters **ap +); + #ifdef NSS_3_4_CODE -/* exposing this for the smart card cache code */ -NSS_EXTERN nssCryptokiInstance * -nssCryptokiInstance_Create + +NSS_EXTERN PRBool +nssToken_IsPresent ( - NSSArena *arena, - NSSToken *t, - CK_OBJECT_HANDLE h, - PRBool isTokenObject + NSSToken *token ); + +NSS_EXTERN nssSession * +nssToken_GetDefaultSession +( + NSSToken *token +); + +NSS_EXTERN PRStatus +nssToken_GetTrustOrder +( + NSSToken *tok +); + +NSS_EXTERN PRStatus +nssToken_NofifyCertsNotVisible +( + NSSToken *tok +); + +NSS_EXTERN PRStatus +nssToken_TraverseCertificates +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRStatus (* callback)(nssCryptokiObject *instance, void *arg), + void *arg +); + #endif PR_END_EXTERN_C diff --git a/security/nss/lib/dev/devm.h b/security/nss/lib/dev/devm.h index d226069c9..0dd0d5b36 100644 --- a/security/nss/lib/dev/devm.h +++ b/security/nss/lib/dev/devm.h @@ -38,25 +38,201 @@ static const char DEVM_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef DEVT_H -#include "devt.h" -#endif /* DEVT_H */ +#ifndef BASE_H +#include "base.h" +#endif /* BASE_H */ #ifndef NSSCKT_H #include "nssckt.h" #endif /* NSSCKT_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ +#ifndef DEV_H +#include "dev.h" +#endif /* DEV_H */ + +#ifndef DEVTM_H +#include "devtm.h" +#endif /* DEVTM_H */ PR_BEGIN_EXTERN_C +/* Shortcut to cryptoki API functions. */ +#define CKAPI(epv) \ + ((CK_FUNCTION_LIST_PTR)(epv)) + +NSS_EXTERN void +nssDevice_AddRef +( + struct nssDeviceBaseStr *device +); + +NSS_EXTERN PRBool +nssDevice_Destroy +( + struct nssDeviceBaseStr *device +); + +NSS_EXTERN PRBool +nssModule_IsThreadSafe +( + NSSModule *module +); + +NSS_EXTERN PRBool +nssModule_IsInternal +( + NSSModule *mod +); + +NSS_EXTERN PRBool +nssModule_IsModuleDBOnly +( + NSSModule *mod +); + +NSS_EXTERN void * +nssModule_GetCryptokiEPV +( + NSSModule *mod +); + +NSS_EXTERN NSSSlot * +nssSlot_Create +( + CK_SLOT_ID slotId, + NSSModule *parent +); + +NSS_EXTERN void * +nssSlot_GetCryptokiEPV +( + NSSSlot *slot +); + +NSS_EXTERN NSSToken * +nssToken_Create +( + CK_SLOT_ID slotID, + NSSSlot *peer +); + +NSS_EXTERN void * +nssToken_GetCryptokiEPV +( + NSSToken *token +); + +NSS_EXTERN nssSession * +nssToken_GetDefaultSession +( + NSSToken *token +); + +NSS_EXTERN PRBool +nssToken_IsLoginRequired +( + NSSToken *token +); + +NSS_EXTERN void +nssToken_Remove +( + NSSToken *token +); + +NSS_EXTERN nssCryptokiObject * +nssCryptokiObject_Create +( + NSSToken *t, + nssSession *session, + CK_OBJECT_HANDLE h +); + +NSS_EXTERN nssTokenObjectCache * +nssTokenObjectCache_Create +( + NSSToken *token, + PRBool cacheCerts, + PRBool cacheTrust, + PRBool cacheCRLs +); + +NSS_EXTERN void +nssTokenObjectCache_Destroy +( + nssTokenObjectCache *cache +); + +NSS_EXTERN void +nssTokenObjectCache_Clear +( + nssTokenObjectCache *cache +); + +NSS_EXTERN PRBool +nssTokenObjectCache_HaveObjectClass +( + nssTokenObjectCache *cache, + CK_OBJECT_CLASS objclass +); + +NSS_EXTERN nssCryptokiObject ** +nssTokenObjectCache_FindObjectsByTemplate +( + nssTokenObjectCache *cache, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR otemplate, + CK_ULONG otlen, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN PRStatus +nssTokenObjectCache_GetObjectAttributes +( + nssTokenObjectCache *cache, + NSSArena *arenaOpt, + nssCryptokiObject *object, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR atemplate, + CK_ULONG atlen +); + +NSS_EXTERN PRStatus +nssTokenObjectCache_ImportObject +( + nssTokenObjectCache *cache, + nssCryptokiObject *object, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR ot, + CK_ULONG otlen +); + +NSS_EXTERN void +nssTokenObjectCache_RemoveObject +( + nssTokenObjectCache *cache, + nssCryptokiObject *object +); + +/* XXX allows peek back into token */ +NSS_EXTERN PRStatus +nssToken_GetCachedObjectAttributes +( + NSSToken *token, + NSSArena *arenaOpt, + nssCryptokiObject *object, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR atemplate, + CK_ULONG atlen +); + /* PKCS#11 stores strings in a fixed-length buffer padded with spaces. This * function gets the length of the actual string. */ NSS_EXTERN PRUint32 -nssPKCS11StringLength( +nssPKCS11String_Length +( CK_CHAR *pkcs11str, PRUint32 bufLen ); diff --git a/security/nss/lib/dev/devmod.c b/security/nss/lib/dev/devmod.c index 455d063e8..e0006370f 100644 --- a/security/nss/lib/dev/devmod.c +++ b/security/nss/lib/dev/devmod.c @@ -35,27 +35,69 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#include "nspr.h" - -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ +#ifndef NSSCKEPV_H +#include "nssckepv.h" +#endif /* NSSCKEPV_H */ #ifndef DEVM_H #include "devm.h" #endif /* DEVM_H */ -#ifndef NSSCKEPV_H -#include "nssckepv.h" -#endif /* NSSCKEPV_H */ - #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ +#ifdef PURE_STAN_CODE + +extern void FC_GetFunctionList(void); +extern void NSC_GetFunctionList(void); +extern void NSC_ModuleDBFunc(void); + +/* The list of boolean flags used to describe properties of a + * module. + */ +#define NSSMODULE_FLAGS_NOT_THREADSAFE 0x0001 /* isThreadSafe */ +#define NSSMODULE_FLAGS_INTERNAL 0x0002 /* isInternal */ +#define NSSMODULE_FLAGS_FIPS 0x0004 /* isFIPS */ +#define NSSMODULE_FLAGS_MODULE_DB 0x0008 /* isModuleDB */ +#define NSSMODULE_FLAGS_MODULE_DB_ONLY 0x0010 /* moduleDBOnly */ +#define NSSMODULE_FLAGS_CRITICAL 0x0020 /* isCritical */ + +struct NSSModuleStr { + struct nssDeviceBaseStr base; + NSSUTF8 *libraryName; + PRLibrary *library; + char *libraryParams; + void *moduleDBFunc; + void *epv; + CK_INFO info; + NSSSlot **slots; + PRUint32 numSlots; + PRBool isLoaded; + struct { + PRInt32 trust; + PRInt32 cipher; + PRInt32 certStorage; + } order; +}; + +#define NSSMODULE_IS_THREADSAFE(module) \ + (!(module->base.flags & NSSMODULE_FLAGS_NOT_THREADSAFE)) + +#define NSSMODULE_IS_INTERNAL(module) \ + (module->base.flags & NSSMODULE_FLAGS_INTERNAL) + +#define NSSMODULE_IS_FIPS(module) \ + (module->base.flags & NSSMODULE_FLAGS_FIPS) + +#define NSSMODULE_IS_MODULE_DB(module) \ + (module->base.flags & NSSMODULE_FLAGS_MODULE_DB) + +#define NSSMODULE_IS_MODULE_DB_ONLY(module) \ + (module->base.flags & NSSMODULE_FLAGS_MODULE_DB_ONLY) + +#define NSSMODULE_IS_CRITICAL(module) \ + (module->base.flags & NSSMODULE_FLAGS_CRITICAL) /* Threading callbacks for C_Initialize. Use NSPR threads. */ @@ -92,6 +134,9 @@ nss_ck_UnlockMutex(CK_VOID_PTR mutex) } /* Default callback args to C_Initialize */ +/* XXX not const because we are modifying the pReserved argument in order + * to use the libraryParams extension. + */ static CK_C_INITIALIZE_ARGS s_ck_initialize_args = { nss_ck_CreateMutex, /* CreateMutex */ @@ -103,55 +148,6 @@ s_ck_initialize_args = { NULL /* pReserved */ }; -/* Alloc memory for a module. Copy in the module name and library path - * if provided. XXX use the opaque arg also, right? - */ -NSS_IMPLEMENT NSSModule * -nssModule_Create -( - NSSUTF8 *moduleOpt, - NSSUTF8 *uriOpt, - NSSUTF8 *opaqueOpt, - void *reserved -) -{ - NSSArena *arena; - NSSModule *rvMod; - arena = NSSArena_Create(); - if(!arena) { - return (NSSModule *)NULL; - } - rvMod = nss_ZNEW(arena, NSSModule); - if (!rvMod) { - goto loser; - } - if (moduleOpt) { - /* XXX making the gross assumption this is just the module name */ - /* if the name is a duplicate, should that be tested here? or - * wait for Load? - */ - rvMod->name = nssUTF8_Duplicate(moduleOpt, arena); - if (!rvMod->name) { - goto loser; - } - } - if (uriOpt) { - /* Load the module from a URI. */ - /* XXX at this time - only file URI (even worse, no file:// for now) */ - rvMod->libraryPath = nssUTF8_Duplicate(uriOpt, arena); - if (!rvMod->libraryPath) { - goto loser; - } - } - rvMod->arena = arena; - rvMod->refCount = 1; - /* everything else is 0/NULL at this point. */ - return rvMod; -loser: - nssArena_Destroy(arena); - return (NSSModule *)NULL; -} - /* load all slots in a module. */ static PRStatus module_load_slots(NSSModule *mod) @@ -163,7 +159,7 @@ module_load_slots(NSSModule *mod) PRStatus nssrv; CK_RV ckrv; /* Get the number of slots */ - ckrv = CKAPI(mod)->C_GetSlotList(CK_FALSE, NULL, &ulNumSlots); + ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, NULL, &ulNumSlots); if (ckrv != CKR_OK) { /* what is the error? */ return PR_FAILURE; @@ -174,26 +170,26 @@ module_load_slots(NSSModule *mod) goto loser; } /* Get the actual slot list */ - ckrv = CKAPI(mod)->C_GetSlotList(CK_FALSE, slotIDs, &ulNumSlots); + ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, slotIDs, &ulNumSlots); if (ckrv != CKR_OK) { /* what is the error? */ goto loser; } /* Alloc memory for the array of slots, in the module's arena */ - mark = nssArena_Mark(mod->arena); + mark = nssArena_Mark(mod->base.arena); /* why mark? it'll be destroyed */ if (!mark) { return PR_FAILURE; } - slots = nss_ZNEWARRAY(mod->arena, NSSSlot *, ulNumSlots); + slots = nss_ZNEWARRAY(mod->base.arena, NSSSlot *, ulNumSlots); if (!slots) { goto loser; } /* Initialize each slot */ for (i=0; i<ulNumSlots; i++) { - slots[i] = nssSlot_Create(mod->arena, slotIDs[i], mod); + slots[i] = nssSlot_Create(slotIDs[i], mod); } nss_ZFreeIf(slotIDs); - nssrv = nssArena_Unmark(mod->arena, mark); + nssrv = nssArena_Unmark(mod->base.arena, mark); if (nssrv != PR_SUCCESS) { goto loser; } @@ -202,44 +198,12 @@ module_load_slots(NSSModule *mod) return PR_SUCCESS; loser: if (mark) { - nssArena_Release(mod->arena, mark); + nssArena_Release(mod->base.arena, mark); } nss_ZFreeIf(slotIDs); return PR_FAILURE; } -/* This is going to take much more thought. The module has a list of slots, - * each of which points to a token. Presumably, all are ref counted. Some - * kind of consistency check is needed here, or perhaps at a higher level. - */ -NSS_IMPLEMENT PRStatus -nssModule_Destroy -( - NSSModule *mod -) -{ - PRUint32 i; - if (--mod->refCount == 0) { - /* Ignore any failure here. */ - for (i=0; i<mod->numSlots; i++) { - nssSlot_Destroy(mod->slots[i]); - } - (void)nssModule_Unload(mod); - return NSSArena_Destroy(mod->arena); - } - return PR_SUCCESS; -} - -NSS_IMPLEMENT NSSModule * -nssModule_AddRef -( - NSSModule *mod -) -{ - ++mod->refCount; - return mod; -} - NSS_IMPLEMENT PRStatus nssModule_Load ( @@ -247,48 +211,79 @@ nssModule_Load ) { PRLibrary *library = NULL; - CK_C_GetFunctionList ep; + CK_C_GetFunctionList epv; CK_RV ckrv; - /* Use NSPR to load the library */ - library = PR_LoadLibrary((char *)mod->libraryPath); - if (!library) { - /* what's the error to set? */ - return PR_FAILURE; + if (NSSMODULE_IS_INTERNAL(mod)) { + /* internal, statically get the C_GetFunctionList function */ + if (NSSMODULE_IS_FIPS(mod)) { + epv = (CK_C_GetFunctionList) FC_GetFunctionList; + } else { + epv = (CK_C_GetFunctionList) NSC_GetFunctionList; + } + if (NSSMODULE_IS_MODULE_DB(mod)) { + mod->moduleDBFunc = (void *) NSC_ModuleDBFunc; + } + if (NSSMODULE_IS_MODULE_DB_ONLY(mod)) { + mod->isLoaded = PR_TRUE; /* XXX needed? */ + return PR_SUCCESS; + } + } else { + /* Use NSPR to load the library */ + library = PR_LoadLibrary(mod->libraryName); + if (!library) { + /* what's the error to set? */ + return PR_FAILURE; + } + mod->library = library; + /* Skip if only getting the db loader function */ + if (!NSSMODULE_IS_MODULE_DB_ONLY(mod)) { + /* Load the cryptoki entry point function */ + epv = (CK_C_GetFunctionList)PR_FindSymbol(library, + "C_GetFunctionList"); + } + /* Load the module database loader function */ + if (NSSMODULE_IS_MODULE_DB(mod)) { + mod->moduleDBFunc = (void *)PR_FindSymbol(library, + "NSS_ReturnModuleSpecData"); + } } - mod->library = library; - /* TODO: semantics here in SECMOD_LoadModule about module db */ - /* Load the cryptoki entry point function */ - ep = (CK_C_GetFunctionList)PR_FindSymbol(library, "C_GetFunctionList"); - if (ep == NULL) { + if (epv == NULL) { goto loser; } /* Load the cryptoki entry point vector (function list) */ - ckrv = (*ep)((CK_FUNCTION_LIST_PTR *)&mod->epv); + ckrv = (*epv)((CK_FUNCTION_LIST_PTR *)&mod->epv); if (ckrv != CKR_OK) { goto loser; } /* Initialize the module */ - /* XXX This is where some additional parameters may need to come in, - * SECMOD_LoadModule has LibraryParameters - */ - ckrv = CKAPI(mod)->C_Initialize(&s_ck_initialize_args); + if (mod->libraryParams) { + s_ck_initialize_args.LibraryParameters = (void *)mod->libraryParams; + } else { + s_ck_initialize_args.LibraryParameters = NULL; + } + ckrv = CKAPI(mod->epv)->C_Initialize(&s_ck_initialize_args); if (ckrv != CKR_OK) { /* Apparently the token is not thread safe. Retry without * threading parameters. */ - mod->flags |= NSSMODULE_FLAGS_NOT_THREADSAFE; - ckrv = CKAPI(mod)->C_Initialize((CK_VOID_PTR)NULL); + mod->base.flags |= NSSMODULE_FLAGS_NOT_THREADSAFE; + ckrv = CKAPI(mod->epv)->C_Initialize((CK_VOID_PTR)NULL); if (ckrv != CKR_OK) { goto loser; } } /* TODO: check the version # using C_GetInfo */ + ckrv = CKAPI(mod->epv)->C_GetInfo(&mod->info); + if (ckrv != CKR_OK) { + goto loser; + } /* TODO: if the name is not set, get it from info.libraryDescription */ /* Now load the slots */ if (module_load_slots(mod) != PR_SUCCESS) { goto loser; } /* Module has successfully loaded */ + mod->isLoaded = PR_TRUE; return PR_SUCCESS; loser: if (library) { @@ -308,15 +303,540 @@ nssModule_Unload { PRStatus nssrv = PR_SUCCESS; if (mod->library) { - (void)CKAPI(mod)->C_Finalize(NULL); + (void)CKAPI(mod->epv)->C_Finalize(NULL); nssrv = PR_UnloadLibrary(mod->library); } /* Free the slots, yes? */ mod->library = NULL; mod->epv = NULL; + mod->isLoaded = PR_FALSE; + return nssrv; +} + +/* Alloc memory for a module. Copy in the module name and library path + * if provided. XXX use the opaque arg also, right? + */ +NSS_IMPLEMENT NSSModule * +nssModule_Create +( + NSSUTF8 *moduleOpt, + NSSUTF8 *uriOpt, + NSSUTF8 *opaqueOpt, + void *reserved +) +{ + NSSArena *arena; + NSSModule *rvMod; + arena = NSSArena_Create(); + if(!arena) { + return (NSSModule *)NULL; + } + rvMod = nss_ZNEW(arena, NSSModule); + if (!rvMod) { + goto loser; + } + if (moduleOpt) { + /* XXX making the gross assumption this is just the module name */ + /* if the name is a duplicate, should that be tested here? or + * wait for Load? + */ + rvMod->base.name = nssUTF8_Duplicate(moduleOpt, arena); + if (!rvMod->base.name) { + goto loser; + } + } + if (uriOpt) { + /* Load the module from a URI. */ + /* XXX at this time - only file URI (even worse, no file:// for now) */ + rvMod->libraryName = nssUTF8_Duplicate(uriOpt, arena); + if (!rvMod->libraryName) { + goto loser; + } + } + rvMod->base.arena = arena; + rvMod->base.refCount = 1; + rvMod->base.lock = PZ_NewLock(nssNSSILockOther); + if (!rvMod->base.lock) { + goto loser; + } + /* everything else is 0/NULL at this point. */ + return rvMod; +loser: + nssArena_Destroy(arena); + return (NSSModule *)NULL; +} + +NSS_EXTERN PRStatus +nssCryptokiArgs_ParseNextPair +( + NSSUTF8 *start, + NSSUTF8 **attrib, + NSSUTF8 **value, + NSSUTF8 **remainder, + NSSArena *arenaOpt +); + +static PRStatus +parse_slot_flags +( + NSSSlot *slot, + NSSUTF8 *slotFlags +) +{ + PRStatus nssrv = PR_SUCCESS; +#if 0 + PRBool done = PR_FALSE; + NSSUTF8 *mark, *last; + last = mark = slotFlags; + while (PR_TRUE) { + while (*mark && *mark != ',') ++mark; + if (!*mark) done = PR_TRUE; + *mark = '\0'; + if (nssUTF8_Equal(last, "RANDOM", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_HAS_RANDOM; + } else if (nssUTF8_Equal(last, "RSA", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RSA; + } else if (nssUTF8_Equal(last, "DSA", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_DSA; + } else if (nssUTF8_Equal(last, "DH", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_DH; + } else if (nssUTF8_Equal(last, "RC2", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RC2; + } else if (nssUTF8_Equal(last, "RC4", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RC4; + } else if (nssUTF8_Equal(last, "RC5", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RC5; + } else if (nssUTF8_Equal(last, "DES", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_DES; + } else if (nssUTF8_Equal(last, "AES", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_AES; + } else if (nssUTF8_Equal(last, "SHA1", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_SHA1; + } else if (nssUTF8_Equal(last, "MD2", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_MD2; + } else if (nssUTF8_Equal(last, "MD5", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_MD5; + } else if (nssUTF8_Equal(last, "SSL", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_SSL; + } else if (nssUTF8_Equal(last, "TLS", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_TLS; + } else if (nssUTF8_Equal(last, "PublicCerts", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_FRIENDLY; + } else { + return PR_FAILURE; + } + if (done) break; + last = ++mark; + } +#endif + return nssrv; +} + +static PRStatus +parse_slot_parameters +( + NSSSlot *slot, + NSSUTF8 *slotParams, + NSSArena *tmparena +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + current = slotParams; + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + if (nssUTF8_Equal(attrib, "slotFlags", &nssrv)) { + nssrv = parse_slot_flags(slot, value); + } else if (nssUTF8_Equal(attrib, "askpw", &nssrv)) { + } else if (nssUTF8_Equal(attrib, "timeout", &nssrv)) { + } + } + if (*remainder == '\0') break; + current = remainder; + } + return nssrv; +} + +/* softoken seems to use "0x0000001", but no standard yet... perhaps this + * should store the number as an ID, in case the input isn't 1,2,3,...? + */ +static PRIntn +get_slot_number(NSSUTF8* snString) +{ + /* XXX super big hack */ + return atoi(&snString[strlen(snString)-1]); +} + +static PRStatus +parse_module_slot_parameters +( + NSSModule *mod, + NSSUTF8 *slotParams +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + NSSArena *tmparena; + PRIntn slotNum; + tmparena = nssArena_Create(); + if (!tmparena) { + return PR_FAILURE; + } + current = slotParams; + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + slotNum = get_slot_number(attrib); + if (slotNum < 0 || slotNum > mod->numSlots) { + return PR_FAILURE; + } + nssrv = parse_slot_parameters(mod->slots[slotNum], + value, tmparena); + if (nssrv != PR_SUCCESS) break; + } + if (*remainder == '\0') break; + current = remainder; + } + return nssrv; +} + +static PRStatus +parse_nss_flags +( + NSSModule *mod, + NSSUTF8 *nssFlags +) +{ + PRStatus nssrv = PR_SUCCESS; + PRBool done = PR_FALSE; + NSSUTF8 *mark, *last; + last = mark = nssFlags; + while (PR_TRUE) { + while (*mark && *mark != ',') ++mark; + if (!*mark) done = PR_TRUE; + *mark = '\0'; + if (nssUTF8_Equal(last, "internal", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_INTERNAL; + } else if (nssUTF8_Equal(last, "moduleDB", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB; + } else if (nssUTF8_Equal(last, "moduleDBOnly", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB_ONLY; + } else if (nssUTF8_Equal(last, "critical", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_CRITICAL; + } else { + return PR_FAILURE; + } + if (done) break; + last = ++mark; + } + return nssrv; +} + +static PRStatus +parse_nss_parameters +( + NSSModule *mod, + NSSUTF8 *nssParams, + NSSArena *tmparena, + NSSUTF8 **slotParams +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + current = nssParams; + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + if (nssUTF8_Equal(attrib, "flags", &nssrv) || + nssUTF8_Equal(attrib, "Flags", &nssrv)) { + nssrv = parse_nss_flags(mod, value); + } else if (nssUTF8_Equal(attrib, "trustOrder", &nssrv)) { + mod->order.trust = atoi(value); + } else if (nssUTF8_Equal(attrib, "cipherOrder", &nssrv)) { + mod->order.cipher = atoi(value); + } else if (nssUTF8_Equal(attrib, "ciphers", &nssrv)) { + } else if (nssUTF8_Equal(attrib, "slotParams", &nssrv)) { + /* slotParams doesn't get an arena, it is handled separately */ + *slotParams = nssUTF8_Duplicate(value, NULL); + } + } + if (*remainder == '\0') break; + current = remainder; + } + return nssrv; +} + +static PRStatus +parse_module_parameters +( + NSSModule *mod, + NSSUTF8 *moduleParams, + NSSUTF8 **slotParams +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + NSSArena *arena = mod->base.arena; + NSSArena *tmparena; + current = moduleParams; + tmparena = nssArena_Create(); + if (!tmparena) { + return PR_FAILURE; + } + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + if (nssUTF8_Equal(attrib, "name", &nssrv)) { + mod->base.name = nssUTF8_Duplicate(value, arena); + } else if (nssUTF8_Equal(attrib, "library", &nssrv)) { + mod->libraryName = nssUTF8_Duplicate(value, arena); + } else if (nssUTF8_Equal(attrib, "parameters", &nssrv)) { + mod->libraryParams = nssUTF8_Duplicate(value, arena); + } else if (nssUTF8_Equal(attrib, "NSS", &nssrv)) { + parse_nss_parameters(mod, value, tmparena, slotParams); + } + } + if (*remainder == '\0') break; + current = remainder; + } + nssArena_Destroy(tmparena); return nssrv; } +static NSSUTF8 ** +get_module_specs +( + NSSModule *mod +) +{ + SECMODModuleDBFunc func = (SECMODModuleDBFunc)mod->moduleDBFunc; + if (func) { + return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND, + mod->libraryParams, + NULL); + } + return NULL; +} + +/* XXX continue working on */ +NSS_IMPLEMENT NSSModule * +nssModule_CreateFromSpec +( + NSSUTF8 *moduleSpec, + NSSModule *parent, + PRBool loadSubModules +) +{ + PRStatus nssrv; + NSSModule *thisModule; + NSSArena *arena; + NSSUTF8 *slotParams = NULL; + arena = nssArena_Create(); + if (!arena) { + return NULL; + } + thisModule = nss_ZNEW(arena, NSSModule); + if (!thisModule) { + goto loser; + } + thisModule->base.lock = PZ_NewLock(nssILockOther); + if (!thisModule->base.lock) { + goto loser; + } + PR_AtomicIncrement(&thisModule->base.refCount); + thisModule->base.arena = arena; + thisModule->base.lock = PZ_NewLock(nssNSSILockOther); + if (!thisModule->base.lock) { + goto loser; + } + nssrv = parse_module_parameters(thisModule, moduleSpec, &slotParams); + if (nssrv != PR_SUCCESS) { + goto loser; + } + nssrv = nssModule_Load(thisModule); + if (nssrv != PR_SUCCESS) { + goto loser; + } + if (slotParams) { + nssrv = parse_module_slot_parameters(thisModule, slotParams); + nss_ZFreeIf(slotParams); + if (nssrv != PR_SUCCESS) { + goto loser; + } + } + if (loadSubModules && NSSMODULE_IS_MODULE_DB(thisModule)) { + NSSUTF8 **moduleSpecs; + NSSUTF8 **index; + /* get the array of sub modules one level below this module */ + moduleSpecs = get_module_specs(thisModule); + /* iterate over the array */ + for (index = moduleSpecs; index && *index; index++) { + NSSModule *child; + /* load the child recursively */ + child = nssModule_CreateFromSpec(*index, thisModule, PR_TRUE); + if (!child) { + /* when children fail, does the parent? */ + nssrv = PR_FAILURE; + break; + } + if (NSSMODULE_IS_CRITICAL(child) && !child->isLoaded) { + nssrv = PR_FAILURE; + nssModule_Destroy(child); + break; + } + nssModule_Destroy(child); + /*nss_ZFreeIf(*index);*/ + } + /*nss_ZFreeIf(moduleSpecs);*/ + } + /* The global list inherits the reference */ + nssrv = nssGlobalModuleList_Add(thisModule); + if (nssrv != PR_SUCCESS) { + goto loser; + } + return thisModule; +loser: + if (thisModule->base.lock) { + PZ_DestroyLock(thisModule->base.lock); + } + nssArena_Destroy(arena); + return (NSSModule *)NULL; +} + +NSS_IMPLEMENT PRStatus +nssModule_Destroy +( + NSSModule *mod +) +{ + PRUint32 i, numSlots; + PR_AtomicDecrement(&mod->base.refCount); + if (mod->base.refCount == 0) { + if (mod->numSlots == 0) { + (void)nssModule_Unload(mod); + return nssArena_Destroy(mod->base.arena); + } else { + numSlots = mod->numSlots; + for (i=0; i<numSlots; i++) { + nssSlot_Destroy(mod->slots[i]); + } + } + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssModule_DestroyFromSlot +( + NSSModule *mod, + NSSSlot *slot +) +{ + PRUint32 i, numSlots = 0; + PR_ASSERT(mod->base.refCount == 0); + for (i=0; i<mod->numSlots; i++) { + if (mod->slots[i] == slot) { + mod->slots[i] = NULL; + } else if (mod->slots[i]) { + numSlots++; + } + } + if (numSlots == 0) { + (void)nssModule_Unload(mod); + return nssArena_Destroy(mod->base.arena); + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT NSSModule * +nssModule_AddRef +( + NSSModule *mod +) +{ + PR_AtomicIncrement(&mod->base.refCount); + return mod; +} + +NSS_IMPLEMENT NSSUTF8 * +nssModule_GetName +( + NSSModule *mod +) +{ + return mod->base.name; +} + +NSS_IMPLEMENT PRBool +nssModule_IsThreadSafe +( + NSSModule *module +) +{ + return NSSMODULE_IS_THREADSAFE(module); +} + +NSS_IMPLEMENT PRBool +nssModule_IsInternal +( + NSSModule *mod +) +{ + return NSSMODULE_IS_INTERNAL(mod); +} + +NSS_IMPLEMENT PRBool +nssModule_IsModuleDBOnly +( + NSSModule *mod +) +{ + return NSSMODULE_IS_MODULE_DB_ONLY(mod); +} + +NSS_IMPLEMENT void * +nssModule_GetCryptokiEPV +( + NSSModule *mod +) +{ + return mod->epv; +} + +NSS_IMPLEMENT NSSSlot ** +nssModule_GetSlots +( + NSSModule *mod +) +{ + PRUint32 i; + NSSSlot **rvSlots; + rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, mod->numSlots + 1); + if (rvSlots) { + for (i=0; i<mod->numSlots; i++) { + rvSlots[i] = nssSlot_AddRef(mod->slots[i]); + } + } + return rvSlots; +} + NSS_IMPLEMENT NSSSlot * nssModule_FindSlotByName ( @@ -326,9 +846,13 @@ nssModule_FindSlotByName { PRUint32 i; PRStatus nssrv; + NSSSlot *slot; + NSSUTF8 *name; for (i=0; i<mod->numSlots; i++) { - if (nssUTF8_Equal(mod->slots[i]->name, slotName, &nssrv)) { - return nssSlot_AddRef(mod->slots[i]); + slot = mod->slots[i]; + name = nssSlot_GetName(slot); + if (nssUTF8_Equal(name, slotName, &nssrv)) { + return nssSlot_AddRef(slot); } if (nssrv != PR_SUCCESS) { break; @@ -337,7 +861,7 @@ nssModule_FindSlotByName return (NSSSlot *)NULL; } -NSS_EXTERN NSSToken * +NSS_IMPLEMENT NSSToken * nssModule_FindTokenByName ( NSSModule *mod, @@ -347,50 +871,30 @@ nssModule_FindTokenByName PRUint32 i; PRStatus nssrv; NSSToken *tok; + NSSUTF8 *name; for (i=0; i<mod->numSlots; i++) { - tok = mod->slots[i]->token; - if (nssUTF8_Equal(tok->name, tokenName, &nssrv)) { - return nssToken_AddRef(tok); - } - if (nssrv != PR_SUCCESS) { - break; + tok = nssSlot_GetToken(mod->slots[i]); + if (tok) { + name = nssToken_GetName(tok); + if (nssUTF8_Equal(name, tokenName, &nssrv)) { + return tok; + } + if (nssrv != PR_SUCCESS) { + break; + } } } return (NSSToken *)NULL; } -NSS_IMPLEMENT PRStatus * -nssModule_TraverseCertificates +NSS_IMPLEMENT PRInt32 +nssModule_GetCertOrder ( - NSSModule *mod, - PRStatus (*callback)(NSSCertificate *c, void *arg), - void *arg + NSSModule *module ) { - return NULL; + return 1; /* XXX */ } -#ifdef DEBUG -void -nssModule_Debug(NSSModule *m) -{ - PRUint32 i; - printf("\n"); - printf("Module Name: %s\n", m->name); - printf("Module Path: %s\n", m->libraryPath); - printf("Number of Slots in Module: %d\n\n", m->numSlots); - for (i=0; i<m->numSlots; i++) { - printf("\tSlot #%d\n", i); - if (m->slots[i]->name) { - printf("\tSlot Name: %s\n", m->slots[i]->name); - } else { - printf("\tSlot Name: <NULL>\n"); - } - if (m->slots[i]->token) { - printf("\tToken Name: %s\n", m->slots[i]->token->name); - } else { - printf("\tToken: <NULL>\n"); - } - } -} -#endif +#endif /* PURE_STAN_BUILD */ + diff --git a/security/nss/lib/dev/devobject.c b/security/nss/lib/dev/devobject.c deleted file mode 100644 index 06150df50..000000000 --- a/security/nss/lib/dev/devobject.c +++ /dev/null @@ -1,1093 +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. - */ - -#ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; -#endif /* DEBUG */ - -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ - -#ifndef DEVM_H -#include "devm.h" -#endif /* DEVM_H */ - -#ifndef NSSCKEPV_H -#include "nssckepv.h" -#endif /* NSSCKEPV_H */ - -#ifndef CKHELPER_H -#include "ckhelper.h" -#endif /* CKHELPER_H */ - -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ - -/* XXX */ -#ifndef PKI_H -#include "pki.h" -#endif /* PKI_H */ - -/* XXX */ -#ifndef NSSPKI_H -#include "nsspki.h" -#endif /* NSSPKI_H */ - -#ifdef NSS_3_4_CODE -#include "pkim.h" /* for cert decoding */ -#include "pk11func.h" /* for PK11_HasRootCerts */ -#endif - -/* The number of object handles to grab during each call to C_FindObjects */ -#define OBJECT_STACK_SIZE 16 - -NSS_IMPLEMENT PRStatus -nssToken_DeleteStoredObject -( - nssCryptokiInstance *instance -) -{ - CK_RV ckrv; - PRStatus nssrv; - PRBool createdSession = PR_FALSE; - NSSToken *token = instance->token; - nssSession *session = NULL; - if (nssCKObject_IsAttributeTrue(instance->handle, CKA_TOKEN, - token->defaultSession, - token->slot, &nssrv)) { - if (nssSession_IsReadWrite(token->defaultSession)) { - session = token->defaultSession; - } else { - session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); - createdSession = PR_TRUE; - } - } - if (session == NULL) { - return PR_FAILURE; - } - nssSession_EnterMonitor(session); - ckrv = CKAPI(token)->C_DestroyObject(session->handle, instance->handle); - nssSession_ExitMonitor(session); - if (createdSession) { - nssSession_Destroy(session); - } - if (ckrv != CKR_OK) { - return PR_FAILURE; - } - return PR_SUCCESS; -} - -static CK_OBJECT_HANDLE -import_object -( - NSSToken *tok, - nssSession *sessionOpt, - CK_ATTRIBUTE_PTR objectTemplate, - CK_ULONG otsize -) -{ - nssSession *session = NULL; - PRBool createdSession = PR_FALSE; - CK_OBJECT_HANDLE object; - CK_RV ckrv; - if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) { - if (sessionOpt) { - if (!nssSession_IsReadWrite(sessionOpt)) { - return CK_INVALID_HANDLE; - } else { - session = sessionOpt; - } - } else if (nssSession_IsReadWrite(tok->defaultSession)) { - session = tok->defaultSession; - } else { - session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE); - createdSession = PR_TRUE; - } - } else { - session = (sessionOpt) ? sessionOpt : tok->defaultSession; - } - if (session == NULL) { - return CK_INVALID_HANDLE; - } - nssSession_EnterMonitor(session); - ckrv = CKAPI(tok->slot)->C_CreateObject(session->handle, - objectTemplate, otsize, - &object); - nssSession_ExitMonitor(session); - if (createdSession) { - nssSession_Destroy(session); - } - if (ckrv != CKR_OK) { - return CK_INVALID_HANDLE; - } - return object; -} - -static CK_OBJECT_HANDLE -find_object_by_template -( - NSSToken *tok, - nssSession *sessionOpt, - CK_ATTRIBUTE_PTR cktemplate, - CK_ULONG ctsize -) -{ - CK_SESSION_HANDLE hSession; - CK_OBJECT_HANDLE rvObject = CK_INVALID_HANDLE; - CK_ULONG count = 0; - CK_RV ckrv; - nssSession *session; - session = (sessionOpt) ? sessionOpt : tok->defaultSession; - hSession = session->handle; - nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_FindObjectsInit(hSession, cktemplate, ctsize); - if (ckrv != CKR_OK) { - nssSession_ExitMonitor(session); - return CK_INVALID_HANDLE; - } - ckrv = CKAPI(tok)->C_FindObjects(hSession, &rvObject, 1, &count); - if (ckrv != CKR_OK) { - nssSession_ExitMonitor(session); - return CK_INVALID_HANDLE; - } - ckrv = CKAPI(tok)->C_FindObjectsFinal(hSession); - nssSession_ExitMonitor(session); - if (ckrv != CKR_OK) { - return CK_INVALID_HANDLE; - } - return rvObject; -} - -static PRStatus -traverse_objects_by_template -( - NSSToken *tok, - nssSession *sessionOpt, - CK_ATTRIBUTE_PTR obj_template, - CK_ULONG otsize, - PRStatus (*callback)(NSSToken *t, nssSession *session, - CK_OBJECT_HANDLE h, void *arg), - void *arg -) -{ - NSSSlot *slot; - PRStatus cbrv; - PRUint32 i; - CK_RV ckrv; - CK_ULONG count; - CK_OBJECT_HANDLE *objectStack; - CK_OBJECT_HANDLE startOS[OBJECT_STACK_SIZE]; - CK_SESSION_HANDLE hSession; - NSSArena *objectArena = NULL; - nssSession *session; - nssList *objectList = NULL; - int objectStackSize = OBJECT_STACK_SIZE; - slot = tok->slot; - objectStack = startOS; - session = (sessionOpt) ? sessionOpt : tok->defaultSession; - hSession = session->handle; - nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_FindObjectsInit(hSession, obj_template, otsize); - if (ckrv != CKR_OK) { - nssSession_ExitMonitor(session); - goto loser; - } - while (PR_TRUE) { - ckrv = CKAPI(slot)->C_FindObjects(hSession, objectStack, - objectStackSize, &count); - if (ckrv != CKR_OK) { - nssSession_ExitMonitor(session); - goto loser; - } - if (count == objectStackSize) { - if (!objectList) { - objectArena = NSSArena_Create(); - objectList = nssList_Create(objectArena, PR_FALSE); - } - nssList_Add(objectList, objectStack); - objectStackSize = objectStackSize * 2; - objectStack = nss_ZNEWARRAY(objectArena, CK_OBJECT_HANDLE, - objectStackSize); - if (objectStack == NULL) { - count =0; - break; - /* return what we can */ - } - } else { - break; - } - } - ckrv = CKAPI(slot)->C_FindObjectsFinal(hSession); - nssSession_ExitMonitor(session); - if (ckrv != CKR_OK) { - goto loser; - } - if (objectList) { - nssListIterator *objects; - CK_OBJECT_HANDLE *localStack; - objects = nssList_CreateIterator(objectList); - objectStackSize = OBJECT_STACK_SIZE; - for (localStack = (CK_OBJECT_HANDLE *)nssListIterator_Start(objects); - localStack != NULL; - localStack = (CK_OBJECT_HANDLE *)nssListIterator_Next(objects)) { - for (i=0; i< objectStackSize; i++) { - cbrv = (*callback)(tok, session, localStack[i], arg); - } - objectStackSize = objectStackSize * 2; - } - nssListIterator_Finish(objects); - nssListIterator_Destroy(objects); - } - for (i=0; i<count; i++) { - cbrv = (*callback)(tok, session, objectStack[i], arg); - } - if (objectArena) - NSSArena_Destroy(objectArena); - return PR_SUCCESS; -loser: - if (objectArena) - NSSArena_Destroy(objectArena); - return PR_FAILURE; -} - -static nssCryptokiInstance * -create_cryptoki_instance -( - NSSArena *arena, - NSSToken *t, - CK_OBJECT_HANDLE h, - PRBool isTokenObject -) -{ - PRStatus nssrv; - nssCryptokiInstance *instance; - CK_ATTRIBUTE cert_template = { CKA_LABEL, NULL, 0 }; - nssrv = nssCKObject_GetAttributes(h, &cert_template, 1, - arena, t->defaultSession, t->slot); - if (nssrv != PR_SUCCESS) { - /* a failure here indicates a device error */ - return NULL; - } - instance = nss_ZNEW(arena, nssCryptokiInstance); - if (!instance) { - return NULL; - } - instance->handle = h; - instance->token = t; - instance->isTokenObject = isTokenObject; - NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template, instance->label); - return instance; -} - -#ifdef NSS_3_4_CODE -/* exposing this for the smart card cache code */ -NSS_IMPLEMENT nssCryptokiInstance * -nssCryptokiInstance_Create -( - NSSArena *arena, - NSSToken *t, - CK_OBJECT_HANDLE h, - PRBool isTokenObject -) -{ - return create_cryptoki_instance(arena, t, h, isTokenObject); -} -#endif - -static NSSCertificateType -nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib) -{ - CK_CERTIFICATE_TYPE ckCertType; - if (!attrib->pValue) { - /* default to PKIX */ - return NSSCertificateType_PKIX; - } - ckCertType = *((CK_ULONG *)attrib->pValue); - switch (ckCertType) { - case CKC_X_509: - return NSSCertificateType_PKIX; - default: - break; - } - return NSSCertificateType_Unknown; -} - -/* Create a certificate from an object handle. */ -static NSSCertificate * -get_token_cert -( - NSSToken *token, - nssSession *sessionOpt, - CK_OBJECT_HANDLE handle -) -{ - NSSCertificate *rvCert; - NSSArena *arena; - nssSession *session; - PRStatus nssrv; - CK_ULONG template_size; - CK_ATTRIBUTE cert_template[] = { - { CKA_CERTIFICATE_TYPE, NULL, 0 }, - { CKA_ID, NULL, 0 }, - { CKA_VALUE, NULL, 0 }, - { CKA_ISSUER, NULL, 0 }, - { CKA_SERIAL_NUMBER, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, - { CKA_NETSCAPE_EMAIL, NULL, 0 } - }; - template_size = sizeof(cert_template) / sizeof(cert_template[0]); - session = (sessionOpt) ? sessionOpt : token->defaultSession; - arena = nssArena_Create(); - if (!arena) { - return NULL; - } - rvCert = nss_ZNEW(arena, NSSCertificate); - if (!rvCert) { - NSSArena_Destroy(arena); - return NULL; - } - nssrv = nssPKIObject_Initialize(&rvCert->object, arena, - token->trustDomain, NULL); - if (nssrv != PR_SUCCESS) { - goto loser; - } - nssrv = nssCKObject_GetAttributes(handle, - cert_template, template_size, - arena, session, token->slot); - if (nssrv != PR_SUCCESS) { - goto loser; - } - rvCert->type = nss_cert_type_from_ck_attrib(&cert_template[0]); - NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[1], &rvCert->id); - NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[2], &rvCert->encoding); - NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[3], &rvCert->issuer); - NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[4], &rvCert->serial); - NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[5], &rvCert->subject); - NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[6], rvCert->email); - /* XXX this would be better accomplished by dividing attributes to - * retrieve into "required" and "optional" - */ - if (rvCert->encoding.size == 0 || - rvCert->issuer.size == 0 || - rvCert->serial.size == 0 || - rvCert->subject.size == 0) - { - /* received a bum object from the token */ - goto loser; - } -#ifdef NSS_3_4_CODE - /* nss 3.4 database doesn't associate email address with cert */ - if (!rvCert->email) { - nssDecodedCert *dc; - NSSASCII7 *email; - dc = nssCertificate_GetDecoding(rvCert); - if (dc) { - email = dc->getEmailAddress(dc); - if (email) - rvCert->email = nssUTF8_Duplicate(email, arena); - } else { - goto loser; - } - } - /* nss 3.4 must deal with tokens that do not follow the PKCS#11 - * standard and return decoded serial numbers. The easiest way to - * work around this is just to grab the serial # from the full encoding - */ - if (PR_TRUE) { - nssDecodedCert *dc; - dc = nssCertificate_GetDecoding(rvCert); - if (dc) { - PRStatus sn_stat; - sn_stat = dc->getDERSerialNumber(dc, &rvCert->serial, arena); - if (sn_stat != PR_SUCCESS) { - goto loser; - } - } else { - goto loser; - } - } -#endif - return rvCert; -loser: - nssPKIObject_Destroy(&rvCert->object); - return (NSSCertificate *)NULL; -} - -NSS_IMPLEMENT PRStatus -nssToken_ImportCertificate -( - NSSToken *tok, - nssSession *sessionOpt, - NSSCertificate *cert, - NSSUTF8 *nickname, - PRBool asTokenObject -) -{ - nssCryptokiInstance *instance; - CK_CERTIFICATE_TYPE cert_type = CKC_X_509; - CK_OBJECT_HANDLE handle; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE cert_tmpl[9]; - CK_ULONG ctsize; - NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); - if (asTokenObject) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } else { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, &cert->id); - NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, &cert->encoding); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, &cert->issuer); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, &cert->subject); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, &cert->serial); - NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); - /* Import the certificate onto the token */ - handle = import_object(tok, sessionOpt, cert_tmpl, ctsize); - if (handle == CK_INVALID_HANDLE) { - return PR_FAILURE; - } - instance = create_cryptoki_instance(cert->object.arena, - tok, handle, asTokenObject); - if (!instance) { - /* XXX destroy object */ - return PR_FAILURE; - } - nssList_Add(cert->object.instanceList, instance); - /* XXX Fix this! */ - nssListIterator_Destroy(cert->object.instances); - cert->object.instances = nssList_CreateIterator(cert->object.instanceList); - return PR_SUCCESS; -} - -static PRBool -compare_cert_by_encoding(void *a, void *b) -{ - NSSCertificate *c1 = (NSSCertificate *)a; - NSSCertificate *c2 = (NSSCertificate *)b; - return (nssItem_Equal(&c1->encoding, &c2->encoding, NULL)); -} - -static PRStatus -retrieve_cert(NSSToken *t, nssSession *session, CK_OBJECT_HANDLE h, void *arg) -{ - PRStatus nssrv; - PRBool found, inCache; - nssTokenCertSearch *search = (nssTokenCertSearch *)arg; - NSSCertificate *cert = NULL; - nssListIterator *instances; - nssCryptokiInstance *ci; - CK_ATTRIBUTE derValue = { CKA_VALUE, NULL, 0 }; - inCache = PR_FALSE; - if (search->cached) { - NSSCertificate csi; /* a fake cert for indexing */ - nssrv = nssCKObject_GetAttributes(h, &derValue, 1, - NULL, session, t->slot); - NSS_CK_ATTRIBUTE_TO_ITEM(&derValue, &csi.encoding); - cert = (NSSCertificate *)nssList_Get(search->cached, &csi); - nss_ZFreeIf(csi.encoding.data); - } - found = PR_FALSE; - if (cert) { - inCache = PR_TRUE; - nssCertificate_AddRef(cert); - instances = cert->object.instances; - for (ci = (nssCryptokiInstance *)nssListIterator_Start(instances); - ci != (nssCryptokiInstance *)NULL; - ci = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { - /* The builtins token will not return the same handle for objects - * during the lifetime of the token. Thus, assuming the found - * object is the same as the cached object if there is already an - * instance for the token. - */ - if (ci->token == t) { - found = PR_TRUE; - break; - } - } - nssListIterator_Finish(instances); - } else { - cert = get_token_cert(t, session, h); - if (!cert) return PR_FAILURE; - } - if (!found) { - PRBool isTokenObject; - /* XXX this is incorrect if the search is over both types */ - isTokenObject = (search->searchType == nssTokenSearchType_TokenOnly) ? - PR_TRUE : PR_FALSE; - ci = create_cryptoki_instance(cert->object.arena, t, h, isTokenObject); - if (!ci) { - NSSCertificate_Destroy(cert); - return PR_FAILURE; - } - nssList_Add(cert->object.instanceList, ci); - /* XXX Fix this! */ - nssListIterator_Destroy(cert->object.instances); - cert->object.instances = nssList_CreateIterator(cert->object.instanceList); - } - if (!inCache) { - nssrv = (*search->callback)(cert, search->cbarg); - } else { - nssrv = PR_SUCCESS; /* cached entries already handled */ - } - NSSCertificate_Destroy(cert); - return nssrv; -} - -/* traverse all certificates - this should only happen if the token - * has been marked as "traversable" - */ -NSS_IMPLEMENT PRStatus -nssToken_TraverseCertificates -( - NSSToken *token, - nssSession *sessionOpt, - nssTokenCertSearch *search -) -{ - PRStatus nssrv; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE cert_template[2]; - CK_ULONG ctsize; - NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); - /* Set the search to token/session only if provided */ - if (search->searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (search->searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); - NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); - if (search->cached) { - nssList_SetCompareFunction(search->cached, compare_cert_by_encoding); - } - nssrv = traverse_objects_by_template(token, sessionOpt, - cert_template, ctsize, - retrieve_cert, search); - return nssrv; -} - -NSS_IMPLEMENT PRStatus -nssToken_TraverseCertificatesBySubject -( - NSSToken *token, - nssSession *sessionOpt, - NSSDER *subject, - nssTokenCertSearch *search -) -{ - PRStatus nssrv; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE subj_template[3]; - CK_ULONG stsize; - NSS_CK_TEMPLATE_START(subj_template, attr, stsize); - /* Set the search to token/session only if provided */ - if (search->searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (search->searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); - NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize); - if (search->cached) { - nssList_SetCompareFunction(search->cached, compare_cert_by_encoding); - } - /* now traverse the token certs matching this template */ - nssrv = traverse_objects_by_template(token, sessionOpt, - subj_template, stsize, - retrieve_cert, search); - return nssrv; -} - -NSS_IMPLEMENT PRStatus -nssToken_TraverseCertificatesByNickname -( - NSSToken *token, - nssSession *sessionOpt, - NSSUTF8 *name, - nssTokenCertSearch *search -) -{ - PRStatus nssrv; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE nick_template[3]; - CK_ULONG ntsize; - NSS_CK_TEMPLATE_START(nick_template, attr, ntsize); - NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name); - /* Set the search to token/session only if provided */ - if (search->searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (search->searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); - NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize); - if (search->cached) { - nssList_SetCompareFunction(search->cached, compare_cert_by_encoding); - } - /* now traverse the token certs matching this template */ - nssrv = traverse_objects_by_template(token, sessionOpt, - nick_template, ntsize, - retrieve_cert, search); - if (nssrv != PR_SUCCESS) { - return nssrv; - } - /* This is to workaround the fact that PKCS#11 doesn't specify - * whether the '\0' should be included. XXX Is that still true? - * im - this is not needed by the current softoken. However, I'm - * leaving it in until I have surveyed more tokens to see if it needed. - * well, its needed by the builtin token... - */ - nick_template[0].ulValueLen++; - nssrv = traverse_objects_by_template(token, sessionOpt, - nick_template, ntsize, - retrieve_cert, search); - return nssrv; -} - -NSS_IMPLEMENT PRStatus -nssToken_TraverseCertificatesByEmail -( - NSSToken *token, - nssSession *sessionOpt, - NSSASCII7 *email, - nssTokenCertSearch *search -) -{ - PRStatus nssrv; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE email_template[3]; - CK_ULONG etsize; - NSS_CK_TEMPLATE_START(email_template, attr, etsize); - NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_EMAIL, email); - /* Set the search to token/session only if provided */ - if (search->searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (search->searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); - NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize); - if (search->cached) { - nssList_SetCompareFunction(search->cached, compare_cert_by_encoding); - } - /* now traverse the token certs matching this template */ - nssrv = traverse_objects_by_template(token, sessionOpt, - email_template, etsize, - retrieve_cert, search); - if (nssrv != PR_SUCCESS) { - return nssrv; - } -#if 0 - /* This is to workaround the fact that PKCS#11 doesn't specify - * whether the '\0' should be included. XXX Is that still true? - */ - email_tmpl[0].ulValueLen--; - nssrv = traverse_objects_by_template(token, sessionOpt, - email_tmpl, etsize, - retrieve_cert, search); -#endif - return nssrv; -} - -/* XXX these next two need to create instances as needed */ - -NSS_IMPLEMENT NSSCertificate * -nssToken_FindCertificateByIssuerAndSerialNumber -( - NSSToken *token, - nssSession *sessionOpt, - NSSDER *issuer, - NSSDER *serial, - nssTokenSearchType searchType -) -{ - NSSCertificate *rvCert = NULL; - nssSession *session; - PRStatus nssrv; - CK_OBJECT_HANDLE object; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE cert_template[4]; - CK_ULONG ctsize; - NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); - /* Set the search to token/session only if provided */ - if (searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - /* Set the unique id */ - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); - NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); - /* get the object handle */ - object = find_object_by_template(token, sessionOpt, cert_template, ctsize); - if (object == CK_INVALID_HANDLE) { - return NULL; - } - session = (sessionOpt) ? sessionOpt : token->defaultSession; - rvCert = get_token_cert(token, sessionOpt, object); - if (rvCert) { - PRBool isTokenObject; - nssCryptokiInstance *instance; - isTokenObject = nssCKObject_IsAttributeTrue(object, CKA_TOKEN, - session, token->slot, - &nssrv); - instance = create_cryptoki_instance(rvCert->object.arena, - token, object, isTokenObject); - if (!instance) { - NSSCertificate_Destroy(rvCert); - return NULL; - } - nssList_Add(rvCert->object.instanceList, instance); - /* XXX Fix this! */ - nssListIterator_Destroy(rvCert->object.instances); - rvCert->object.instances = nssList_CreateIterator(rvCert->object.instanceList); - } - return rvCert; -} - -NSS_IMPLEMENT NSSCertificate * -nssToken_FindCertificateByEncodedCertificate -( - NSSToken *token, - nssSession *sessionOpt, - NSSBER *encodedCertificate, - nssTokenSearchType searchType -) -{ - NSSCertificate *rvCert = NULL; - nssSession *session; - PRStatus nssrv; - CK_OBJECT_HANDLE object; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE cert_template[3]; - CK_ULONG ctsize; - NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); - /* Set the search to token/session only if provided */ - if (searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate); - NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); - /* get the object handle */ - object = find_object_by_template(token, sessionOpt, cert_template, ctsize); - if (object == CK_INVALID_HANDLE) { - return NULL; - } - session = (sessionOpt) ? sessionOpt : token->defaultSession; - rvCert = get_token_cert(token, sessionOpt, object); - if (rvCert) { - PRBool isTokenObject; - nssCryptokiInstance *instance; - isTokenObject = nssCKObject_IsAttributeTrue(object, CKA_TOKEN, - session, token->slot, - &nssrv); - instance = create_cryptoki_instance(rvCert->object.arena, - token, object, isTokenObject); - if (!instance) { - NSSCertificate_Destroy(rvCert); - return NULL; - } - nssList_Add(rvCert->object.instanceList, instance); - /* XXX Fix this! */ - nssListIterator_Destroy(rvCert->object.instances); - rvCert->object.instances = nssList_CreateIterator(rvCert->object.instanceList); - } - return rvCert; -} - -static void -sha1_hash(NSSItem *input, NSSItem *output) -{ - NSSAlgorithmAndParameters *ap; - NSSToken *token = STAN_GetDefaultCryptoToken(); - ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL); - (void)nssToken_Digest(token, NULL, ap, input, output, NULL); -#ifdef NSS_3_4_CODE - PK11_FreeSlot(token->pk11slot); -#endif - nss_ZFreeIf(ap); -} - -static void -md5_hash(NSSItem *input, NSSItem *output) -{ - NSSAlgorithmAndParameters *ap; - NSSToken *token = STAN_GetDefaultCryptoToken(); - ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL); - (void)nssToken_Digest(token, NULL, ap, input, output, NULL); -#ifdef NSS_3_4_CODE - PK11_FreeSlot(token->pk11slot); -#endif - nss_ZFreeIf(ap); -} - -NSS_IMPLEMENT PRStatus -nssToken_ImportTrust -( - NSSToken *tok, - nssSession *sessionOpt, - NSSTrust *trust, - PRBool asTokenObject -) -{ - CK_OBJECT_HANDLE handle; - CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE trust_tmpl[10]; - CK_ULONG tsize; - PRUint8 sha1[20]; /* this is cheating... */ - PRUint8 md5[16]; - NSSItem sha1_result, md5_result; - NSSCertificate *c = trust->certificate; - sha1_result.data = sha1; sha1_result.size = sizeof sha1; - md5_result.data = md5; md5_result.size = sizeof md5; - sha1_hash(&c->encoding, &sha1_result); - md5_hash(&c->encoding, &md5_result); - NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize); - if (asTokenObject) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } else { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, &c->issuer); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, &c->serial); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH, &md5_result); - /* now set the trust values */ - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, trust->serverAuth); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, trust->clientAuth); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, trust->codeSigning); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, - trust->emailProtection); - NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize); - /* import the trust object onto the token */ - handle = import_object(tok, NULL, trust_tmpl, tsize); - if (handle != CK_INVALID_HANDLE) { - nssCryptokiInstance *instance; - instance = create_cryptoki_instance(trust->object.arena, - tok, handle, asTokenObject); - if (!instance) { - return PR_FAILURE; - } - nssList_Add(trust->object.instanceList, instance); - /* XXX Fix this! */ - nssListIterator_Destroy(trust->object.instances); - trust->object.instances = nssList_CreateIterator(trust->object.instanceList); - tok->hasNoTrust = PR_FALSE; - return PR_SUCCESS; - } - return PR_FAILURE; -} - -NSS_IMPLEMENT PRStatus -nssToken_SetTrustCache -( - NSSToken *token -) -{ - CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE tobj_template[2]; - CK_ULONG tobj_size; - CK_OBJECT_HANDLE obj; - nssSession *session = token->defaultSession; - - NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); - - obj = find_object_by_template(token, session, - tobj_template, tobj_size); - token->hasNoTrust = PR_FALSE; - if (obj == CK_INVALID_HANDLE) { - token->hasNoTrust = PR_TRUE; - } - return PR_SUCCESS; -} - -NSS_IMPLEMENT PRStatus -nssToken_SetCrlCache -( - NSSToken *token -) -{ - CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_CRL; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE tobj_template[2]; - CK_ULONG tobj_size; - CK_OBJECT_HANDLE obj; - nssSession *session = token->defaultSession; - - NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); - - obj = find_object_by_template(token, session, - tobj_template, tobj_size); - token->hasNoCrls = PR_TRUE; - if (obj == CK_INVALID_HANDLE) { - token->hasNoCrls = PR_TRUE; - } - return PR_SUCCESS; -} - -static CK_OBJECT_HANDLE -get_cert_trust_handle -( - NSSToken *token, - nssSession *session, - NSSCertificate *c, - nssTokenSearchType searchType -) -{ - CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE tobj_template[5]; - CK_ULONG tobj_size; - PRUint8 sha1[20]; /* this is cheating... */ - NSSItem sha1_result; - - if (token->hasNoTrust) { - return CK_INVALID_HANDLE; - } - sha1_result.data = sha1; sha1_result.size = sizeof sha1; - sha1_hash(&c->encoding, &sha1_result); - NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); - if (searchType == nssTokenSearchType_SessionOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); - } else if (searchType == nssTokenSearchType_TokenOnly) { - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); - } - NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); -#ifdef NSS_3_4_CODE - if (!PK11_HasRootCerts(token->pk11slot)) { -#endif - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, &c->issuer); - NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , &c->serial); -#ifdef NSS_3_4_CODE - } - /* - * we need to arrange for the built-in token to lose the bottom 2 - * attributes so that old built-in tokens will continue to work. - */ -#endif - NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); - return find_object_by_template(token, session, - tobj_template, tobj_size); -} - -NSS_IMPLEMENT NSSTrust * -nssToken_FindTrustForCert -( - NSSToken *token, - nssSession *sessionOpt, - NSSCertificate *c, - nssTokenSearchType searchType -) -{ - PRStatus nssrv; - NSSTrust *rvTrust; - nssSession *session; - NSSArena *arena; - nssCryptokiInstance *instance; - PRBool isTokenObject; - CK_BBOOL isToken; - CK_TRUST saTrust, caTrust, epTrust, csTrust; - CK_OBJECT_HANDLE tobjID; - CK_ATTRIBUTE_PTR attr; - CK_ATTRIBUTE trust_template[5]; - CK_ULONG trust_size; - session = (sessionOpt) ? sessionOpt : token->defaultSession; - tobjID = get_cert_trust_handle(token, session, c, searchType); - if (tobjID == CK_INVALID_HANDLE) { - return NULL; - } - /* Then use the trust object to find the trust settings */ - NSS_CK_TEMPLATE_START(trust_template, attr, trust_size); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust); - NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust); - NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size); - nssrv = nssCKObject_GetAttributes(tobjID, - trust_template, trust_size, - NULL, session, token->slot); - if (nssrv != PR_SUCCESS) { - return NULL; - } - arena = nssArena_Create(); - if (!arena) { - return NULL; - } - rvTrust = nss_ZNEW(arena, NSSTrust); - if (!rvTrust) { - nssArena_Destroy(arena); - return NULL; - } - nssrv = nssPKIObject_Initialize(&rvTrust->object, arena, - token->trustDomain, NULL); - if (nssrv != PR_SUCCESS) { - goto loser; - } - isTokenObject = (isToken == CK_TRUE) ? PR_TRUE : PR_FALSE; - instance = create_cryptoki_instance(arena, token, tobjID, isTokenObject); - if (!instance) { - goto loser; - } - rvTrust->serverAuth = saTrust; - rvTrust->clientAuth = caTrust; - rvTrust->emailProtection = epTrust; - rvTrust->codeSigning = csTrust; - return rvTrust; -loser: - nssPKIObject_Destroy(&rvTrust->object); - return (NSSTrust *)NULL; -} - diff --git a/security/nss/lib/dev/devslot.c b/security/nss/lib/dev/devslot.c index a113b46f5..843a5bd4b 100644 --- a/security/nss/lib/dev/devslot.c +++ b/security/nss/lib/dev/devslot.c @@ -35,34 +35,62 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ +#ifndef NSSCKEPV_H +#include "nssckepv.h" +#endif /* NSSCKEPV_H */ #ifndef DEVM_H #include "devm.h" #endif /* DEVM_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11.h" -#else -#ifndef NSSCKEPV_H -#include "nssckepv.h" -#endif /* NSSCKEPV_H */ -#endif /* NSS_3_4_CODE */ - #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ +/* measured in seconds */ +#define NSSSLOT_TOKEN_DELAY_TIME 10 + +/* this should track global and per-transaction login information */ + +#ifdef PURE_STAN_CODE +typedef enum { + nssSlotAskPasswordTimes_FirstTime = 0, + nssSlotAskPasswordTimes_EveryTime = 1, + nssSlotAskPasswordTimes_Timeout = 2 +} +nssSlotAskPasswordTimes; + +struct nssSlotAuthInfoStr +{ + PRTime lastLogin; + nssSlotAskPasswordTimes askTimes; + PRIntervalTime askPasswordTimeout; +}; + +struct NSSSlotStr +{ + struct nssDeviceBaseStr base; + NSSModule *module; /* Parent */ + NSSToken *token; /* Peer */ + CK_SLOT_ID slotID; + CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ + struct nssSlotAuthInfoStr authInfo; + PRIntervalTime lastTokenPing; +#ifdef NSS_3_4_CODE + PK11SlotInfo *pk11slot; +#endif +}; +#endif /* PURE_STAN_CODE */ + +#define NSSSLOT_IS_FRIENDLY(slot) \ + (slot->base.flags & NSSSLOT_FLAGS_FRIENDLY) + +/* measured as interval */ +static PRIntervalTime s_token_delay_time = 0; /* The flags needed to open a read-only session. */ static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION; -#ifdef PURE_STAN /* In pk11slot.c, this was a no-op. So it is here also. */ static CK_RV PR_CALLBACK nss_ck_slot_notify @@ -74,56 +102,41 @@ nss_ck_slot_notify { return CKR_OK; } -#endif -/* maybe this should really inherit completely from the module... I dunno, - * any uses of slots where independence is needed? - */ +#ifdef PURE_STAN_BUILD NSS_IMPLEMENT NSSSlot * nssSlot_Create ( - NSSArena *arenaOpt, CK_SLOT_ID slotID, NSSModule *parent ) { NSSArena *arena = NULL; - nssArenaMark *mark = NULL; NSSSlot *rvSlot; NSSToken *token = NULL; NSSUTF8 *slotName = NULL; PRUint32 length; - PRBool newArena; - PRStatus nssrv; CK_SLOT_INFO slotInfo; CK_RV ckrv; - if (arenaOpt) { - arena = arenaOpt; - mark = nssArena_Mark(arena); - if (!mark) { - return (NSSSlot *)NULL; - } - newArena = PR_FALSE; - } else { - arena = NSSArena_Create(); - if(!arena) { - return (NSSSlot *)NULL; - } - newArena = PR_TRUE; + void *epv; + arena = NSSArena_Create(); + if(!arena) { + return (NSSSlot *)NULL; } rvSlot = nss_ZNEW(arena, NSSSlot); if (!rvSlot) { goto loser; } /* Get slot information */ - ckrv = CKAPI(parent)->C_GetSlotInfo(slotID, &slotInfo); + epv = nssModule_GetCryptokiEPV(parent); + ckrv = CKAPI(epv)->C_GetSlotInfo(slotID, &slotInfo); if (ckrv != CKR_OK) { /* set an error here, eh? */ goto loser; } /* Grab the slot description from the PKCS#11 fixed-length buffer */ - length = nssPKCS11StringLength(slotInfo.slotDescription, - sizeof(slotInfo.slotDescription)); + length = nssPKCS11String_Length(slotInfo.slotDescription, + sizeof(slotInfo.slotDescription)); if (length > 0) { slotName = nssUTF8_Create(arena, nssStringType_UTF8String, (void *)slotInfo.slotDescription, length); @@ -131,45 +144,31 @@ nssSlot_Create goto loser; } } - if (!arenaOpt) { - /* Avoid confusion now - only set the slot's arena to a non-NULL value - * if a new arena is created. Otherwise, depend on the caller (having - * passed arenaOpt) to free the arena. - */ - rvSlot->arena = arena; + rvSlot->base.arena = arena; + rvSlot->base.refCount = 1; + rvSlot->base.name = slotName; + rvSlot->base.lock = PZ_NewLock(nssNSSILockOther); /* XXX */ + if (!rvSlot->base.lock) { + goto loser; } - rvSlot->refCount = 1; - rvSlot->epv = parent->epv; - rvSlot->module = parent; - rvSlot->name = slotName; + rvSlot->module = parent; /* refs go from module to slots */ rvSlot->slotID = slotID; rvSlot->ckFlags = slotInfo.flags; /* Initialize the token if present. */ if (slotInfo.flags & CKF_TOKEN_PRESENT) { - token = nssToken_Create(arena, slotID, rvSlot); + token = nssToken_Create(slotID, rvSlot); if (!token) { goto loser; } } rvSlot->token = token; - if (mark) { - nssrv = nssArena_Unmark(arena, mark); - if (nssrv != PR_SUCCESS) { - goto loser; - } - } return rvSlot; loser: - if (newArena) { - nssArena_Destroy(arena); - } else { - if (mark) { - nssArena_Release(arena, mark); - } - } + nssArena_Destroy(arena); /* everything was created in the arena, nothing to see here, move along */ return (NSSSlot *)NULL; } +#endif /* PURE_STAN_BUILD */ NSS_IMPLEMENT PRStatus nssSlot_Destroy @@ -177,46 +176,316 @@ nssSlot_Destroy NSSSlot *slot ) { - if (--slot->refCount == 0) { -#ifndef NSS_3_4_CODE - /* Not going to do this in 3.4, maybe never */ - nssToken_Destroy(slot->token); + if (slot) { + PR_AtomicDecrement(&slot->base.refCount); + if (slot->base.refCount == 0) { + PZ_DestroyLock(slot->base.lock); +#ifdef PURE_STAN_BUILD + nssToken_Destroy(slot->token); + nssModule_DestroyFromSlot(slot->module, slot); #endif - if (slot->arena) { - return NSSArena_Destroy(slot->arena); - } else { - nss_ZFreeIf(slot); + return nssArena_Destroy(slot->base.arena); } } return PR_SUCCESS; } +NSS_IMPLEMENT void +NSSSlot_Destroy +( + NSSSlot *slot +) +{ + (void)nssSlot_Destroy(slot); +} + NSS_IMPLEMENT NSSSlot * nssSlot_AddRef ( NSSSlot *slot ) { - ++slot->refCount; + PR_AtomicIncrement(&slot->base.refCount); return slot; } NSS_IMPLEMENT NSSUTF8 * nssSlot_GetName ( + NSSSlot *slot +) +{ + return slot->base.name; +} + +NSS_IMPLEMENT NSSUTF8 * +nssSlot_GetTokenName +( + NSSSlot *slot +) +{ + return nssToken_GetName(slot->token); +} + +static PRBool +within_token_delay_period(NSSSlot *slot) +{ + PRIntervalTime time, lastTime; + /* Set the delay time for checking the token presence */ + if (s_token_delay_time == 0) { + s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME); + } + time = PR_IntervalNow(); + lastTime = slot->lastTokenPing; + if ((time > lastTime) && ((time - lastTime) < s_token_delay_time)) { + return PR_TRUE; + } + slot->lastTokenPing = time; + return PR_FALSE; +} + +NSS_IMPLEMENT PRBool +nssSlot_IsTokenPresent +( + NSSSlot *slot +) +{ + CK_RV ckrv; + PRStatus nssrv; + /* XXX */ + nssSession *session; + CK_SLOT_INFO slotInfo; + void *epv; + /* permanent slots are always present */ + if (nssSlot_IsPermanent(slot)) { + return PR_TRUE; + } + /* avoid repeated calls to check token status within set interval */ + if (within_token_delay_period(slot)) { + return (PRBool)((slot->ckFlags & CKF_TOKEN_PRESENT) != 0); + } + /* First obtain the slot info */ +#ifdef PURE_STAN_BUILD + epv = nssModule_GetCryptokiEPV(slot->module); +#else + epv = slot->epv; +#endif + if (!epv) { + return PR_FALSE; + } + ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo); + if (ckrv != CKR_OK) { + slot->token->base.name[0] = 0; /* XXX */ + return PR_FALSE; + } + slot->ckFlags = slotInfo.flags; + /* check for the presence of the token */ + if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) { + if (!slot->token) { + /* token was ne'er present */ + return PR_FALSE; + } + session = nssToken_GetDefaultSession(slot->token); + nssSession_EnterMonitor(session); + /* token is not present */ + if (session->handle != CK_INVALID_SESSION) { + /* session is valid, close and invalidate it */ + CKAPI(epv)->C_CloseSession(session->handle); + session->handle = CK_INVALID_SESSION; + } + nssSession_ExitMonitor(session); +#ifdef NSS_3_4_CODE + if (slot->token->base.name[0] != 0) { + /* notify the high-level cache that the token is removed */ + slot->token->base.name[0] = 0; /* XXX */ + nssToken_NofifyCertsNotVisible(slot->token); + } +#endif + slot->token->base.name[0] = 0; /* XXX */ + /* clear the token cache */ + nssToken_Remove(slot->token); + return PR_FALSE; +#ifdef PURE_STAN_CODE + } else if (!slot->token) { + /* token was not present at boot time, is now */ + slot->token = nssToken_Create(slot->slotID, slot); + return (slot->token != NULL); +#endif + } + /* token is present, use the session info to determine if the card + * has been removed and reinserted. + */ + session = nssToken_GetDefaultSession(slot->token); + nssSession_EnterMonitor(session); + if (session->handle != CK_INVALID_SESSION) { + CK_SESSION_INFO sessionInfo; + ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo); + if (ckrv != CKR_OK) { + /* session is screwy, close and invalidate it */ + CKAPI(epv)->C_CloseSession(session->handle); + session->handle = CK_INVALID_SESSION; + } + } + nssSession_ExitMonitor(session); + /* token not removed, finished */ + if (session->handle != CK_INVALID_SESSION) { + return PR_TRUE; + } else { + /* token has been removed, need to refresh with new session */ + nssrv = nssSlot_Refresh(slot); + if (nssrv != PR_SUCCESS) { + slot->token->base.name[0] = 0; /* XXX */ + return PR_FALSE; + } + return PR_TRUE; + } +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT NSSModule * +nssSlot_GetModule +( + NSSSlot *slot +) +{ + return nssModule_AddRef(slot->module); +} +#endif /* PURE_STAN_BUILD */ + +NSS_IMPLEMENT void * +nssSlot_GetCryptokiEPV +( + NSSSlot *slot +) +{ +#ifdef PURE_STAN_BUILD + return nssModule_GetCryptokiEPV(slot->module); +#else + return slot->epv; +#endif +} + +NSS_IMPLEMENT NSSToken * +nssSlot_GetToken +( + NSSSlot *slot +) +{ + if (nssSlot_IsTokenPresent(slot)) { + return nssToken_AddRef(slot->token); + } + return (NSSToken *)NULL; +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT PRBool +nssSlot_IsPermanent +( + NSSSlot *slot +) +{ + return (!(slot->ckFlags & CKF_REMOVABLE_DEVICE)); +} + +NSS_IMPLEMENT PRBool +nssSlot_IsFriendly +( + NSSSlot *slot +) +{ + return PR_TRUE /* XXX NSSSLOT_IS_FRIENDLY(slot)*/; +} + +NSS_IMPLEMENT PRBool +nssSlot_IsHardware +( + NSSSlot *slot +) +{ + return (slot->ckFlags & CKF_HW_SLOT); +} + +NSS_IMPLEMENT PRStatus +nssSlot_Refresh +( + NSSSlot *slot +) +{ + /* XXX */ +#if 0 + nssToken_Destroy(slot->token); + if (slotInfo.flags & CKF_TOKEN_PRESENT) { + slot->token = nssToken_Create(NULL, slotID, slot); + } +#endif + return PR_SUCCESS; +} + +static PRBool +slot_needs_login +( NSSSlot *slot, - NSSArena *arenaOpt + nssSession *session ) { - if (slot->name) { - return nssUTF8_Duplicate(slot->name, arenaOpt); + PRBool needsLogin, logout; + struct nssSlotAuthInfoStr *authInfo = &slot->authInfo; + void *epv = nssModule_GetCryptokiEPV(slot->module); + if (!nssToken_IsLoginRequired(slot->token)) { + return PR_FALSE; + } + if (authInfo->askTimes == nssSlotAskPasswordTimes_EveryTime) { + logout = PR_TRUE; + } else if (authInfo->askTimes == nssSlotAskPasswordTimes_Timeout) { + PRIntervalTime currentTime = PR_IntervalNow(); + if (authInfo->lastLogin - currentTime < authInfo->askPasswordTimeout) { + logout = PR_FALSE; + } else { + logout = PR_TRUE; + } + } else { /* nssSlotAskPasswordTimes_FirstTime */ + logout = PR_FALSE; + } + if (logout) { + /* The login has expired, timeout */ + nssSession_EnterMonitor(session); + CKAPI(epv)->C_Logout(session->handle); + nssSession_ExitMonitor(session); + needsLogin = PR_TRUE; + } else { + CK_RV ckrv; + CK_SESSION_INFO sessionInfo; + nssSession_EnterMonitor(session); + ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo); + nssSession_ExitMonitor(session); + if (ckrv != CKR_OK) { + /* XXX error -- invalidate session */ + return PR_FALSE; + } + switch (sessionInfo.state) { + case CKS_RW_PUBLIC_SESSION: + case CKS_RO_PUBLIC_SESSION: + default: + needsLogin = PR_TRUE; + break; + case CKS_RW_USER_FUNCTIONS: + case CKS_RW_SO_FUNCTIONS: + case CKS_RO_USER_FUNCTIONS: + needsLogin = PR_FALSE; + break; + } } - return (NSSUTF8 *)NULL; + return needsLogin; } static PRStatus -nssslot_login(NSSSlot *slot, nssSession *session, - CK_USER_TYPE userType, NSSCallback *pwcb) +slot_login +( + NSSSlot *slot, + nssSession *session, + CK_USER_TYPE userType, + NSSCallback *pwcb +) { PRStatus nssrv; PRUint32 attempts; @@ -224,15 +493,19 @@ nssslot_login(NSSSlot *slot, nssSession *session, NSSUTF8 *password = NULL; CK_ULONG pwLen; CK_RV ckrv; + void *epv; if (!pwcb->getPW) { /* set error INVALID_ARG */ return PR_FAILURE; } + epv = nssModule_GetCryptokiEPV(slot->module); keepTrying = PR_TRUE; nssrv = PR_FAILURE; attempts = 0; while (keepTrying) { - nssrv = pwcb->getPW(slot->name, &attempts, pwcb->arg, &password); + /* use the token name, since it is present */ + NSSUTF8 *tokenName = nssToken_GetName(slot->token); + nssrv = pwcb->getPW(tokenName, attempts, pwcb->arg, &password); if (nssrv != PR_SUCCESS) { nss_SetError(NSS_ERROR_USER_CANCELED); break; @@ -242,8 +515,8 @@ nssslot_login(NSSSlot *slot, nssSession *session, break; } nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_Login(session->handle, userType, - (CK_CHAR_PTR)password, pwLen); + ckrv = CKAPI(epv)->C_Login(session->handle, userType, + (CK_CHAR_PTR)password, pwLen); nssSession_ExitMonitor(session); switch (ckrv) { case CKR_OK: @@ -265,129 +538,130 @@ nssslot_login(NSSSlot *slot, nssSession *session, password = NULL; ++attempts; } - nss_ZFreeIf(password); return nssrv; } static PRStatus -nssslot_init_password(NSSSlot *slot, nssSession *rwSession, NSSCallback *pwcb) +init_slot_password +( + NSSSlot *slot, + nssSession *rwSession, + NSSUTF8 *password +) { - NSSUTF8 *userPW = NULL; - NSSUTF8 *ssoPW = NULL; - PRStatus nssrv; + PRStatus status; + NSSUTF8 *ssoPW = ""; CK_ULONG userPWLen, ssoPWLen; CK_RV ckrv; - if (!pwcb->getInitPW) { - /* set error INVALID_ARG */ - return PR_FAILURE; - } + void *epv = nssModule_GetCryptokiEPV(slot->module); /* Get the SO and user passwords */ - nssrv = pwcb->getInitPW(slot->name, pwcb->arg, &ssoPW, &userPW); - if (nssrv != PR_SUCCESS) goto loser; - userPWLen = (CK_ULONG)nssUTF8_Length(userPW, &nssrv); - if (nssrv != PR_SUCCESS) goto loser; - ssoPWLen = (CK_ULONG)nssUTF8_Length(ssoPW, &nssrv); - if (nssrv != PR_SUCCESS) goto loser; + userPWLen = (CK_ULONG)nssUTF8_Length(password, &status); + if (status != PR_SUCCESS) { + goto loser; + } + ssoPWLen = (CK_ULONG)nssUTF8_Length(ssoPW, &status); + if (status != PR_SUCCESS) { + goto loser; + } /* First log in as SO */ - ckrv = CKAPI(slot)->C_Login(rwSession->handle, CKU_SO, - (CK_CHAR_PTR)ssoPW, ssoPWLen); + ckrv = CKAPI(epv)->C_Login(rwSession->handle, CKU_SO, + (CK_CHAR_PTR)ssoPW, ssoPWLen); if (ckrv != CKR_OK) { /* set error ...SO_LOGIN_FAILED */ goto loser; } /* Now change the user PIN */ - ckrv = CKAPI(slot)->C_InitPIN(rwSession->handle, - (CK_CHAR_PTR)userPW, userPWLen); + ckrv = CKAPI(epv)->C_InitPIN(rwSession->handle, + (CK_CHAR_PTR)password, userPWLen); if (ckrv != CKR_OK) { /* set error */ goto loser; } - nss_ZFreeIf(ssoPW); - nss_ZFreeIf(userPW); return PR_SUCCESS; loser: - nss_ZFreeIf(ssoPW); - nss_ZFreeIf(userPW); return PR_FAILURE; } static PRStatus -nssslot_change_password(NSSSlot *slot, nssSession *rwSession, NSSCallback *pwcb) +change_slot_password +( + NSSSlot *slot, + nssSession *rwSession, + NSSUTF8 *oldPassword, + NSSUTF8 *newPassword +) { - NSSUTF8 *userPW = NULL; - NSSUTF8 *newPW = NULL; - PRUint32 attempts; - PRStatus nssrv; - PRBool keepTrying = PR_TRUE; + PRStatus status; CK_ULONG userPWLen, newPWLen; CK_RV ckrv; - if (!pwcb->getNewPW) { - /* set error INVALID_ARG */ - return PR_FAILURE; + void *epv = nssModule_GetCryptokiEPV(slot->module); + userPWLen = (CK_ULONG)nssUTF8_Length(oldPassword, &status); + if (status != PR_SUCCESS) { + return status; } - attempts = 0; - while (keepTrying) { - nssrv = pwcb->getNewPW(slot->name, &attempts, pwcb->arg, - &userPW, &newPW); - if (nssrv != PR_SUCCESS) { - nss_SetError(NSS_ERROR_USER_CANCELED); - break; - } - userPWLen = (CK_ULONG)nssUTF8_Length(userPW, &nssrv); - if (nssrv != PR_SUCCESS) return nssrv; - newPWLen = (CK_ULONG)nssUTF8_Length(newPW, &nssrv); - if (nssrv != PR_SUCCESS) return nssrv; - nssSession_EnterMonitor(rwSession); - ckrv = CKAPI(slot)->C_SetPIN(rwSession->handle, - (CK_CHAR_PTR)userPW, userPWLen, - (CK_CHAR_PTR)newPW, newPWLen); - nssSession_ExitMonitor(rwSession); - switch (ckrv) { - case CKR_OK: - slot->authInfo.lastLogin = PR_Now(); - nssrv = PR_SUCCESS; - keepTrying = PR_FALSE; - break; - case CKR_PIN_INCORRECT: - nss_SetError(NSS_ERROR_INVALID_PASSWORD); - keepTrying = PR_TRUE; /* received bad pw, keep going */ - break; - default: - nssrv = PR_FAILURE; - keepTrying = PR_FALSE; - break; - } - nss_ZFreeIf(userPW); - nss_ZFreeIf(newPW); - userPW = NULL; - newPW = NULL; - ++attempts; + newPWLen = (CK_ULONG)nssUTF8_Length(newPassword, &status); + if (status != PR_SUCCESS) { + return status; } - nss_ZFreeIf(userPW); - nss_ZFreeIf(newPW); - return nssrv; + nssSession_EnterMonitor(rwSession); + ckrv = CKAPI(epv)->C_SetPIN(rwSession->handle, + (CK_CHAR_PTR)oldPassword, userPWLen, + (CK_CHAR_PTR)newPassword, newPWLen); + nssSession_ExitMonitor(rwSession); + switch (ckrv) { + case CKR_OK: + slot->authInfo.lastLogin = PR_Now(); + status = PR_SUCCESS; + break; + case CKR_PIN_INCORRECT: + nss_SetError(NSS_ERROR_INVALID_PASSWORD); + status = PR_FAILURE; + break; + default: + status = PR_FAILURE; + break; + } + return status; } NSS_IMPLEMENT PRStatus nssSlot_Login ( NSSSlot *slot, - PRBool asSO, NSSCallback *pwcb ) { - PRBool needsLogin, needsInit; - CK_USER_TYPE userType; - userType = (asSO) ? CKU_SO : CKU_USER; - needsInit = PR_FALSE; /* XXX */ - needsLogin = PR_TRUE; /* XXX */ - if (needsInit) { - return nssSlot_SetPassword(slot, pwcb); - } else if (needsLogin) { - return nssslot_login(slot, slot->token->defaultSession, - userType, pwcb); - } - return PR_SUCCESS; /* login not required */ + PRStatus status; + CK_USER_TYPE userType = CKU_USER; + NSSToken *token = nssSlot_GetToken(slot); + nssSession *session; + if (!token) { + return PR_FAILURE; + } + if (!nssToken_IsLoginRequired(token)) { + nssToken_Destroy(token); + return PR_SUCCESS; + } + session = nssToken_GetDefaultSession(slot->token); + if (nssToken_NeedsPINInitialization(token)) { + NSSUTF8 *password = NULL; + if (!pwcb->getInitPW) { + nssToken_Destroy(token); + return PR_FAILURE; /* don't know how to get initial password */ + } + status = (*pwcb->getInitPW)(slot->base.name, pwcb->arg, &password); + if (status == PR_SUCCESS) { + session = nssSlot_CreateSession(slot, NULL, PR_TRUE); + status = init_slot_password(slot, session, password); + nssSession_Destroy(session); + } + } else if (slot_needs_login(slot, session)) { + status = slot_login(slot, session, userType, pwcb); + } else { + status = PR_SUCCESS; + } + nssToken_Destroy(token); + return status; } NSS_IMPLEMENT PRStatus @@ -397,12 +671,15 @@ nssSlot_Logout nssSession *sessionOpt ) { - nssSession *session; PRStatus nssrv = PR_SUCCESS; + nssSession *session; CK_RV ckrv; - session = (sessionOpt) ? sessionOpt : slot->token->defaultSession; + void *epv = nssModule_GetCryptokiEPV(slot->module); + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(slot->token); nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_Logout(session->handle); + ckrv = CKAPI(epv)->C_Logout(session->handle); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { /* translate the error */ @@ -411,6 +688,16 @@ nssSlot_Logout return nssrv; } +NSS_IMPLEMENT PRBool +nssSlot_IsLoggedIn +( + NSSSlot *slot +) +{ + nssSession *session = nssToken_GetDefaultSession(slot->token); + return !slot_needs_login(slot, session); +} + NSS_IMPLEMENT void nssSlot_SetPasswordDefaults ( @@ -421,28 +708,36 @@ nssSlot_SetPasswordDefaults slot->authInfo.askPasswordTimeout = askPasswordTimeout; } + NSS_IMPLEMENT PRStatus nssSlot_SetPassword ( NSSSlot *slot, - NSSCallback *pwcb + NSSUTF8 *oldPasswordOpt, + NSSUTF8 *newPassword ) { - PRStatus nssrv; + PRStatus status; nssSession *rwSession; - PRBool needsInit; - needsInit = PR_FALSE; /* XXX */ + NSSToken *token = nssSlot_GetToken(slot); + if (!token) { + return PR_FAILURE; + } rwSession = nssSlot_CreateSession(slot, NULL, PR_TRUE); - if (needsInit) { - nssrv = nssslot_init_password(slot, rwSession, pwcb); + if (nssToken_NeedsPINInitialization(token)) { + status = init_slot_password(slot, rwSession, newPassword); + } else if (oldPasswordOpt) { + status = change_slot_password(slot, rwSession, + oldPasswordOpt, newPassword); } else { - nssrv = nssslot_change_password(slot, rwSession, pwcb); + /* old password must be given in order to change */ + status = PR_FAILURE; } nssSession_Destroy(rwSession); - return nssrv; + nssToken_Destroy(token); + return status; } -#ifdef PURE_STAN NSS_IMPLEMENT nssSession * nssSlot_CreateSession ( @@ -453,18 +748,15 @@ nssSlot_CreateSession { CK_RV ckrv; CK_FLAGS ckflags; - CK_SESSION_HANDLE session; + CK_SESSION_HANDLE handle; + void *epv = nssModule_GetCryptokiEPV(slot->module); nssSession *rvSession; ckflags = s_ck_readonly_flags; if (readWrite) { ckflags |= CKF_RW_SESSION; } - /* does the opening and closing of sessions need to be done in a - * threadsafe manner? should there be a "meta-lock" controlling - * calls like this? - */ - ckrv = CKAPI(slot)->C_OpenSession(slot->slotID, ckflags, - slot, nss_ck_slot_notify, &session); + ckrv = CKAPI(epv)->C_OpenSession(slot->slotID, ckflags, + slot, nss_ck_slot_notify, &handle); if (ckrv != CKR_OK) { /* set an error here, eh? */ return (nssSession *)NULL; @@ -473,7 +765,7 @@ nssSlot_CreateSession if (!rvSession) { return (nssSession *)NULL; } - if (slot->module->flags & NSSMODULE_FLAGS_NOT_THREADSAFE) { + if (!nssModule_IsThreadSafe(slot->module)) { /* If the parent module is not threadsafe, create lock to manage * session within threads. */ @@ -487,7 +779,7 @@ nssSlot_CreateSession return (nssSession *)NULL; } } - rvSession->handle = session; + rvSession->handle = handle; rvSession->slot = slot; rvSession->isRW = readWrite; return rvSession; @@ -501,7 +793,8 @@ nssSession_Destroy { CK_RV ckrv = CKR_OK; if (s) { - ckrv = CKAPI(s->slot)->C_CloseSession(s->handle); + void *epv = s->slot->epv; + ckrv = CKAPI(epv)->C_CloseSession(s->handle); if (s->lock) { PZ_DestroyLock(s->lock); } @@ -509,7 +802,7 @@ nssSession_Destroy } return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; } -#endif +#endif /* PURE_STAN_BUILD */ NSS_IMPLEMENT PRStatus nssSession_EnterMonitor diff --git a/security/nss/lib/dev/devt.h b/security/nss/lib/dev/devt.h index ef031524b..10a7978c3 100644 --- a/security/nss/lib/dev/devt.h +++ b/security/nss/lib/dev/devt.h @@ -72,81 +72,70 @@ PR_BEGIN_EXTERN_C typedef struct nssSessionStr nssSession; -/* The list of boolean flags used to describe properties of a - * module. - */ -#define NSSMODULE_FLAGS_NOT_THREADSAFE 0x0001 /* isThreadSafe */ - -struct NSSModuleStr { - NSSArena *arena; - PRInt32 refCount; - NSSUTF8 *name; - NSSUTF8 *libraryPath; - PRLibrary *library; - void *epv; - NSSSlot **slots; - PRUint32 numSlots; - PRUint32 flags; -}; - -/* The list of boolean flags used to describe properties of a - * slot. - */ -#define NSSSLOT_FLAGS_LOGIN_REQUIRED 0x0001 /* needLogin */ -/*#define NSSSLOT_FLAGS_READONLY 0x0002*/ /* readOnly */ - -/* this should track global and per-transaction login information */ -struct nssSlotAuthInfoStr +/* XXX until NSSTokenStr is moved */ +struct nssDeviceBaseStr { - PRTime lastLogin; - PRInt32 askPasswordTimeout; + NSSArena *arena; + PZLock *lock; + PRInt32 refCount; + NSSUTF8 *name; + PRUint32 flags; }; -struct NSSSlotStr -{ - NSSArena *arena; - PRInt32 refCount; - NSSModule *module; /* Parent */ - NSSToken *token; /* Child (or peer, if you will) */ - NSSUTF8 *name; - CK_SLOT_ID slotID; - void *epv; - CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ - PRUint32 flags; - struct nssSlotAuthInfoStr authInfo; - NSSTrustDomain *trustDomain; -#ifdef NSS_3_4_CODE - PK11SlotInfo *pk11slot; -#endif -}; +typedef struct nssTokenObjectCacheStr nssTokenObjectCache; +/* XXX until devobject.c goes away */ struct NSSTokenStr { - NSSArena *arena; - PRInt32 refCount; + struct nssDeviceBaseStr base; NSSSlot *slot; /* Parent (or peer, if you will) */ - NSSUTF8 *name; CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */ PRUint32 flags; void *epv; nssSession *defaultSession; NSSTrustDomain *trustDomain; PRIntervalTime lastTime; - PRBool hasNoTrust; - PRBool hasNoCrls; + nssTokenObjectCache *cache; #ifdef NSS_3_4_CODE PK11SlotInfo *pk11slot; - nssList *certList; /* local cache of certs for slow tokens */ - PRBool loggedIn; +#endif +}; + +typedef enum { + nssSlotAskPasswordTimes_FirstTime = 0, + nssSlotAskPasswordTimes_EveryTime = 1, + nssSlotAskPasswordTimes_Timeout = 2 +} +nssSlotAskPasswordTimes; + +struct nssSlotAuthInfoStr +{ + PRTime lastLogin; + nssSlotAskPasswordTimes askTimes; + PRIntervalTime askPasswordTimeout; +}; + +struct NSSSlotStr +{ + struct nssDeviceBaseStr base; + NSSModule *module; /* Parent */ + NSSToken *token; /* Peer */ + CK_SLOT_ID slotID; + CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ + struct nssSlotAuthInfoStr authInfo; + PRIntervalTime lastTokenPing; +#ifdef NSS_3_4_CODE + void *epv; + PK11SlotInfo *pk11slot; #endif }; struct nssSessionStr { - PZLock *lock; - CK_SESSION_HANDLE handle; - NSSSlot *slot; - PRBool isRW; + PZLock *lock; + CK_SESSION_HANDLE handle; + NSSSlot *slot; + PRBool isRW; }; typedef enum { @@ -155,15 +144,17 @@ typedef enum { } NSSCertificateType; #ifdef nodef +/* the current definition of NSSTrust depends on this value being CK_ULONG */ +typedef CK_ULONG nssTrustLevel; +#else typedef enum { nssTrustLevel_Unknown = 0, nssTrustLevel_NotTrusted = 1, nssTrustLevel_Trusted = 2, nssTrustLevel_TrustedDelegator = 3, - nssTrustLevel_Valid = 4 + nssTrustLevel_Valid = 4, + nssTrustLevel_ValidDelegator = 5 } nssTrustLevel; -#else -typedef CK_ULONG nssTrustLevel; /* for now */ #endif typedef struct nssCryptokiInstanceStr nssCryptokiInstance; @@ -176,12 +167,15 @@ struct nssCryptokiInstanceStr NSSUTF8 *label; }; +typedef struct nssCryptokiInstanceStr nssCryptokiObject; + typedef struct nssTokenCertSearchStr nssTokenCertSearch; typedef enum { nssTokenSearchType_AllObjects = 0, nssTokenSearchType_SessionOnly = 1, - nssTokenSearchType_TokenOnly = 2 + nssTokenSearchType_TokenOnly = 2, + nssTokenSearchType_TokenForced = 3 } nssTokenSearchType; struct nssTokenCertSearchStr @@ -195,6 +189,9 @@ struct nssTokenCertSearchStr */ }; +struct nssSlotListStr; +typedef struct nssSlotListStr nssSlotList; + struct NSSAlgorithmAndParametersStr { CK_MECHANISM mechanism; diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c index b3b168a5f..a43ed43f4 100644 --- a/security/nss/lib/dev/devtoken.c +++ b/security/nss/lib/dev/devtoken.c @@ -35,74 +35,68 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ +#ifndef NSSCKEPV_H +#include "nssckepv.h" +#endif /* NSSCKEPV_H */ #ifndef DEVM_H #include "devm.h" #endif /* DEVM_H */ -#ifndef NSSCKEPV_H -#include "nssckepv.h" -#endif /* NSSCKEPV_H */ - #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ +#ifdef NSS_3_4_CODE +#include "pk11func.h" +#include "dev3hack.h" +#endif + +/* The number of object handles to grab during each call to C_FindObjects */ +#define OBJECT_STACK_SIZE 16 + +#ifdef PURE_STAN_BUILD +struct NSSTokenStr +{ + struct nssDeviceBaseStr base; + NSSSlot *slot; /* Peer */ + CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */ + nssSession *defaultSession; + nssTokenObjectCache *cache; +}; -/* maybe this should really inherit completely from the module... I dunno, - * any uses of slots where independence is needed? - */ NSS_IMPLEMENT NSSToken * nssToken_Create ( - NSSArena *arenaOpt, CK_SLOT_ID slotID, - NSSSlot *parent + NSSSlot *peer ) { NSSArena *arena; - nssArenaMark *mark = NULL; NSSToken *rvToken; nssSession *session = NULL; NSSUTF8 *tokenName = NULL; PRUint32 length; - PRBool newArena; PRBool readWrite; - PRStatus nssrv; CK_TOKEN_INFO tokenInfo; CK_RV ckrv; - if (arenaOpt) { - arena = arenaOpt; - mark = nssArena_Mark(arena); - if (!mark) { - return (NSSToken *)NULL; - } - newArena = PR_FALSE; - } else { - arena = NSSArena_Create(); - if(!arena) { - return (NSSToken *)NULL; - } - newArena = PR_TRUE; + void *epv = nssSlot_GetCryptokiEPV(peer); + arena = NSSArena_Create(); + if(!arena) { + return (NSSToken *)NULL; } rvToken = nss_ZNEW(arena, NSSToken); if (!rvToken) { goto loser; } /* Get token information */ - ckrv = CKAPI(parent)->C_GetTokenInfo(slotID, &tokenInfo); + ckrv = CKAPI(epv)->C_GetTokenInfo(slotID, &tokenInfo); if (ckrv != CKR_OK) { /* set an error here, eh? */ goto loser; } /* Grab the slot description from the PKCS#11 fixed-length buffer */ - length = nssPKCS11StringLength(tokenInfo.label, sizeof(tokenInfo.label)); + length = nssPKCS11String_Length(tokenInfo.label, sizeof(tokenInfo.label)); if (length > 0) { tokenName = nssUTF8_Create(arena, nssStringType_UTF8String, (void *)tokenInfo.label, length); @@ -117,28 +111,26 @@ nssToken_Create } else { readWrite = PR_FALSE; } - session = nssSlot_CreateSession(parent, arena, readWrite); + session = nssSlot_CreateSession(peer, arena, readWrite); if (session == NULL) { goto loser; } /* TODO: seed the RNG here */ - if (!arenaOpt) { - /* Avoid confusion now - only set the token's arena to a non-NULL value - * if a new arena is created. Otherwise, depend on the caller (having - * passed arenaOpt) to free the arena. - */ - rvToken->arena = arena; + rvToken->base.arena = arena; + rvToken->base.refCount = 1; + rvToken->base.name = tokenName; + rvToken->base.lock = PZ_NewLock(nssNSSILockOther); /* XXX */ + if (!rvToken->base.lock) { + goto loser; } - rvToken->refCount = 1; - rvToken->slot = parent; - rvToken->name = tokenName; + rvToken->slot = peer; /* slot owns ref to token */ rvToken->ckFlags = tokenInfo.flags; rvToken->defaultSession = session; - rvToken->hasNoTrust = PR_FALSE; - rvToken->hasNoCrls = PR_FALSE; - if (mark) { - nssrv = nssArena_Unmark(arena, mark); - if (nssrv != PR_SUCCESS) { + if (nssSlot_IsHardware(peer)) { + rvToken->cache = nssTokenObjectCache_Create(rvToken, + PR_TRUE, PR_TRUE, PR_TRUE); + if (!rvToken->cache) { + nssSlot_Destroy(peer); goto loser; } } @@ -147,15 +139,10 @@ loser: if (session) { nssSession_Destroy(session); } - if (newArena) { - nssArena_Destroy(arena); - } else { - if (mark) { - nssArena_Release(arena, mark); - } - } + nssArena_Destroy(arena); return (NSSToken *)NULL; } +#endif /* PURE_STAN_BUILD */ NSS_IMPLEMENT PRStatus nssToken_Destroy @@ -163,141 +150,1238 @@ nssToken_Destroy NSSToken *tok ) { - if (--tok->refCount == 0) { -#ifndef NSS_3_4_CODE - /* don't do this in 3.4 -- let PK11SlotInfo handle it */ - if (tok->defaultSession) { - nssSession_Destroy(tok->defaultSession); - } - if (tok->arena) { - return NSSArena_Destroy(tok->arena); - } else { - nss_ZFreeIf(tok); + if (tok) { + PR_AtomicDecrement(&tok->base.refCount); + if (tok->base.refCount == 0) { + PZ_DestroyLock(tok->base.lock); + nssTokenObjectCache_Destroy(tok->cache); + return nssArena_Destroy(tok->base.arena); } -#else - nss_ZFreeIf(tok); -#endif } return PR_SUCCESS; } +NSS_IMPLEMENT void +nssToken_Remove +( + NSSToken *tok +) +{ + nssTokenObjectCache_Clear(tok->cache); +} + +NSS_IMPLEMENT void +NSSToken_Destroy +( + NSSToken *tok +) +{ + (void)nssToken_Destroy(tok); +} + NSS_IMPLEMENT NSSToken * nssToken_AddRef ( NSSToken *tok ) { - ++tok->refCount; + PR_AtomicIncrement(&tok->base.refCount); return tok; } +NSS_IMPLEMENT NSSSlot * +nssToken_GetSlot +( + NSSToken *tok +) +{ + return nssSlot_AddRef(tok->slot); +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT NSSModule * +nssToken_GetModule +( + NSSToken *token +) +{ + return nssSlot_GetModule(token->slot); +} +#endif + +NSS_IMPLEMENT void * +nssToken_GetCryptokiEPV +( + NSSToken *token +) +{ + return nssSlot_GetCryptokiEPV(token->slot); +} + +NSS_IMPLEMENT nssSession * +nssToken_GetDefaultSession +( + NSSToken *token +) +{ + return token->defaultSession; +} + NSS_IMPLEMENT NSSUTF8 * nssToken_GetName ( NSSToken *tok ) { - if (tok->name[0] == 0) { - (void) nssToken_IsPresent(tok); + if (tok == NULL) { + return ""; + } + if (tok->base.name[0] == 0) { + (void) nssSlot_IsTokenPresent(tok->slot); } - return tok->name; + return tok->base.name; +} + +NSS_IMPLEMENT NSSUTF8 * +NSSToken_GetName +( + NSSToken *token +) +{ + return nssToken_GetName(token); } NSS_IMPLEMENT PRBool -nssToken_IsPresent +nssToken_IsLoginRequired +( + NSSToken *token +) +{ + return (token->ckFlags & CKF_LOGIN_REQUIRED); +} + +NSS_IMPLEMENT PRBool +nssToken_NeedsPINInitialization ( NSSToken *token ) { + return (!(token->ckFlags & CKF_USER_PIN_INITIALIZED)); +} + +NSS_IMPLEMENT PRStatus +nssToken_DeleteStoredObject +( + nssCryptokiObject *instance +) +{ CK_RV ckrv; - PRStatus nssrv; - nssSession *session; - CK_SLOT_INFO slotInfo; - NSSSlot *slot = token->slot; - PRIntervalTime time,lastTime; - static PRIntervalTime delayTime = 0; - - session = token->defaultSession; - /* permanent slots are always present */ - if (nssSlot_IsPermanent(slot) && session != CK_INVALID_SESSION) { - return PR_TRUE; - } - - if (delayTime == 0) { - delayTime = PR_SecondsToInterval(10); - } - - time = PR_IntervalNow(); - lastTime = token->lastTime; - if ((time > lastTime) && ((time - lastTime) < delayTime)) { - return (PRBool) ((slot->ckFlags & CKF_TOKEN_PRESENT) != 0); - } - token->lastTime = time; + PRStatus status; + PRBool createdSession = PR_FALSE; + NSSToken *token = instance->token; + nssSession *session = NULL; + void *epv = nssToken_GetCryptokiEPV(instance->token); + if (token->cache) { + nssTokenObjectCache_RemoveObject(token->cache, instance); + } + if (instance->isTokenObject) { + if (nssSession_IsReadWrite(token->defaultSession)) { + session = token->defaultSession; + } else { + session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); + createdSession = PR_TRUE; + } + } + if (session == NULL) { + return PR_FAILURE; + } nssSession_EnterMonitor(session); - /* First obtain the slot info */ - ckrv = CKAPI(slot)->C_GetSlotInfo(slot->slotID, &slotInfo); - if (ckrv != CKR_OK) { - nssSession_ExitMonitor(session); - token->name[0] = 0; - return PR_FALSE; - } - slot->ckFlags = slotInfo.flags; - /* check for the presence of the token */ - if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) { - /* token is not present */ - if (session->handle != CK_INVALID_SESSION) { - /* session is valid, close and invalidate it */ - CKAPI(slot)->C_CloseSession(session->handle); - session->handle = CK_INVALID_SESSION; + ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle); + nssSession_ExitMonitor(session); + if (createdSession) { + nssSession_Destroy(session); + } + status = (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; + return status; +} + +static nssCryptokiObject * +import_object +( + NSSToken *tok, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR objectTemplate, + CK_ULONG otsize +) +{ + nssSession *session = NULL; + PRBool createdSession = PR_FALSE; + nssCryptokiObject *object = NULL; + CK_OBJECT_HANDLE handle; + CK_RV ckrv; + void *epv = nssToken_GetCryptokiEPV(tok); + if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) { + if (sessionOpt) { + if (!nssSession_IsReadWrite(sessionOpt)) { + return CK_INVALID_HANDLE; + } else { + session = sessionOpt; + } + } else if (nssSession_IsReadWrite(tok->defaultSession)) { + session = tok->defaultSession; + } else { + session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE); + createdSession = PR_TRUE; + } + } else { + session = (sessionOpt) ? sessionOpt : tok->defaultSession; + } + if (session == NULL) { + return CK_INVALID_HANDLE; + } + nssSession_EnterMonitor(session); + ckrv = CKAPI(epv)->C_CreateObject(session->handle, + objectTemplate, otsize, + &handle); + nssSession_ExitMonitor(session); + if (ckrv == CKR_OK) { + object = nssCryptokiObject_Create(tok, session, handle); + } + if (createdSession) { + nssSession_Destroy(session); + } + return object; +} + +static nssCryptokiObject ** +create_objects_from_handles +( + NSSToken *tok, + nssSession *session, + CK_OBJECT_HANDLE *handles, + PRUint32 numH +) +{ + nssCryptokiObject **objects; + objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1); + if (objects) { + PRInt32 i; + for (i=0; i<(PRInt32)numH; i++) { + objects[i] = nssCryptokiObject_Create(tok, session, handles[i]); + if (!objects[i]) { + for (--i; i>0; --i) { + nssCryptokiObject_Destroy(objects[i]); + } + return (nssCryptokiObject **)NULL; + } } + } + return objects; +} + +static nssCryptokiObject ** +find_objects +( + NSSToken *tok, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR obj_template, + CK_ULONG otsize, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_RV ckrv; + CK_ULONG count; + CK_OBJECT_HANDLE *objectHandles; + PRUint32 arraySize, numHandles; + void *epv = nssToken_GetCryptokiEPV(tok); + nssCryptokiObject **objects; + NSSArena *arena; + nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; + /* the arena is only for the array of object handles */ + arena = nssArena_Create(); + if (!arena) { + if (statusOpt) *statusOpt = PR_FAILURE; + return (nssCryptokiObject **)NULL; + } + if (maximumOpt > 0) { + arraySize = maximumOpt; + } else { + arraySize = OBJECT_STACK_SIZE; + } + numHandles = 0; + objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize); + if (!objectHandles) { + goto loser; + } + nssSession_EnterMonitor(session); /* ==== session lock === */ + /* Initialize the find with the template */ + ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, + obj_template, otsize); + if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); - token->name[0] = 0; - return PR_FALSE; + goto loser; } - /* token is present, use the session info to determine if the card - * has been removed and reinserted. - */ - if (session != CK_INVALID_SESSION) { - CK_SESSION_INFO sessionInfo; - ckrv = CKAPI(slot)->C_GetSessionInfo(session->handle, &sessionInfo); + while (PR_TRUE) { + /* Issue the find for up to arraySize - numHandles objects */ + ckrv = CKAPI(epv)->C_FindObjects(session->handle, + objectHandles + numHandles, + arraySize - numHandles, + &count); if (ckrv != CKR_OK) { - /* session is screwy, close and invalidate it */ - CKAPI(slot)->C_CloseSession(session->handle); - session->handle = CK_INVALID_SESSION; + nssSession_ExitMonitor(session); + goto loser; + } + /* bump the number of found objects */ + numHandles += count; + if (maximumOpt > 0 || numHandles < arraySize) { + /* When a maximum is provided, the search is done all at once, + * so the search is finished. If the number returned was less + * than the number sought, the search is finished. + */ + break; + } + /* the array is filled, double it and continue */ + arraySize *= 2; + objectHandles = nss_ZREALLOCARRAY(objectHandles, + CK_OBJECT_HANDLE, + arraySize); + if (!objectHandles) { + nssSession_ExitMonitor(session); + goto loser; } } - nssSession_ExitMonitor(session); - /* token not removed, finished */ - if (session->handle != CK_INVALID_SESSION) { - return PR_TRUE; + ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); + nssSession_ExitMonitor(session); /* ==== end session lock === */ + if (ckrv != CKR_OK) { + goto loser; + } + if (numHandles > 0) { + objects = create_objects_from_handles(tok, session, + objectHandles, numHandles); } else { - /* token has been removed, need to refresh with new session */ - nssrv = nssSlot_Refresh(slot); - if (nssrv != PR_SUCCESS) { - token->name[0] = 0; - return PR_FALSE; + objects = NULL; + } + nssArena_Destroy(arena); + if (statusOpt) *statusOpt = PR_SUCCESS; + return objects; +loser: + nssArena_Destroy(arena); + if (statusOpt) *statusOpt = PR_FAILURE; + return (nssCryptokiObject **)NULL; +} + +static nssCryptokiObject ** +find_objects_by_template +( + NSSToken *token, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR obj_template, + CK_ULONG otsize, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_OBJECT_CLASS objclass; + nssCryptokiObject **objects = NULL; + PRUint32 i; + for (i=0; i<otsize; i++) { + if (obj_template[i].type == CKA_CLASS) { + objclass = *(CK_OBJECT_CLASS *)obj_template[i].pValue; + break; + } + } + PR_ASSERT(i < otsize); + /* If these objects are being cached, try looking there first */ + if (token->cache && + nssTokenObjectCache_HaveObjectClass(token->cache, objclass)) + { + PRStatus status; + objects = nssTokenObjectCache_FindObjectsByTemplate(token->cache, + objclass, + obj_template, + otsize, + maximumOpt, + &status); + if (status == PR_SUCCESS) { + if (statusOpt) *statusOpt = status; + return objects; } - return PR_TRUE; } + /* Either they are not cached, or cache failed; look on token. */ + objects = find_objects(token, sessionOpt, + obj_template, otsize, + maximumOpt, statusOpt); + return objects; } -NSS_IMPLEMENT PRBool -nssToken_HasCrls +NSS_IMPLEMENT nssCryptokiObject * +nssToken_ImportCertificate +( + NSSToken *tok, + nssSession *sessionOpt, + NSSCertificateType certType, + NSSItem *id, + NSSUTF8 *nickname, + NSSDER *encoding, + NSSDER *issuer, + NSSDER *subject, + NSSDER *serial, + NSSASCII7 *email, + PRBool asTokenObject +) +{ + CK_CERTIFICATE_TYPE cert_type; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_tmpl[10]; + CK_ULONG ctsize; + nssTokenSearchType searchType; + nssCryptokiObject *rvObject = NULL; + + if (certType == NSSCertificateType_PKIX) { + cert_type = CKC_X_509; + } else { + return (nssCryptokiObject *)NULL; + } + NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); + if (asTokenObject) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + searchType = nssTokenSearchType_TokenOnly; + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + searchType = nssTokenSearchType_SessionOnly; + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); + if (email) { + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_EMAIL, email); + } + NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); + /* see if the cert is already there */ + rvObject = nssToken_FindCertificateByIssuerAndSerialNumber(tok, + sessionOpt, + issuer, + serial, + searchType, + NULL); + if (rvObject) { + NSSSlot *slot = nssToken_GetSlot(tok); + nssSession *session = nssSlot_CreateSession(slot, NULL, PR_TRUE); + if (!session) { + nssCryptokiObject_Destroy(rvObject); + return (nssCryptokiObject *)NULL; + } + /* according to PKCS#11, label, ID, issuer, and serial number + * may change after the object has been created. For PKIX, the + * last two attributes can't change, so for now we'll only worry + * about the first two. + */ + NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); + NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); + /* reset the mutable attributes on the token */ + nssCKObject_SetAttributes(rvObject->handle, + cert_tmpl, ctsize, + session, slot); + if (!rvObject->label && nickname) { + rvObject->label = nssUTF8_Duplicate(nickname, NULL); + } + nssSession_Destroy(session); + nssSlot_Destroy(slot); + } else { + /* Import the certificate onto the token */ + rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize); + } + if (rvObject && tok->cache) { + /* The cache will overwrite the attributes if the object already + * exists. + */ + nssTokenObjectCache_ImportObject(tok->cache, rvObject, + CKO_CERTIFICATE, + cert_tmpl, ctsize); + } + return rvObject; +} + +/* traverse all certificates - this should only happen if the token + * has been marked as "traversable" + */ +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificates ( - NSSToken *tok + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt ) { - return !tok->hasNoCrls; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[2]; + CK_ULONG ctsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); + + if (searchType == nssTokenSearchType_TokenForced) { + objects = find_objects(token, sessionOpt, + cert_template, ctsize, + maximumOpt, statusOpt); + } else { + objects = find_objects_by_template(token, sessionOpt, + cert_template, ctsize, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesBySubject +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE subj_template[3]; + CK_ULONG stsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(subj_template, attr, stsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize); + /* now locate the token certs matching this template */ + objects = find_objects_by_template(token, sessionOpt, + subj_template, stsize, + maximumOpt, statusOpt); + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesByNickname +( + NSSToken *token, + nssSession *sessionOpt, + NSSUTF8 *name, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE nick_template[3]; + CK_ULONG ntsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(nick_template, attr, ntsize); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize); + /* now locate the token certs matching this template */ + objects = find_objects_by_template(token, sessionOpt, + nick_template, ntsize, + maximumOpt, statusOpt); + if (!objects) { + /* This is to workaround the fact that PKCS#11 doesn't specify + * whether the '\0' should be included. XXX Is that still true? + * im - this is not needed by the current softoken. However, I'm + * leaving it in until I have surveyed more tokens to see if it needed. + * well, its needed by the builtin token... + */ + nick_template[0].ulValueLen++; + objects = find_objects_by_template(token, sessionOpt, + nick_template, ntsize, + maximumOpt, statusOpt); + } + return objects; +} + +/* XXX + * This function *does not* use the token object cache, because not even + * the softoken will return a value for CKA_NETSCAPE_EMAIL from a call + * to GetAttributes. The softoken does allow searches with that attribute, + * it just won't return a value for it. + */ +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesByEmail +( + NSSToken *token, + nssSession *sessionOpt, + NSSASCII7 *email, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE email_template[3]; + CK_ULONG etsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(email_template, attr, etsize); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_EMAIL, email); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize); + /* now locate the token certs matching this template */ + objects = find_objects(token, sessionOpt, + email_template, etsize, + maximumOpt, statusOpt); + if (!objects) { + /* This is to workaround the fact that PKCS#11 doesn't specify + * whether the '\0' should be included. XXX Is that still true? + * im - this is not needed by the current softoken. However, I'm + * leaving it in until I have surveyed more tokens to see if it needed. + * well, its needed by the builtin token... + */ + email_template[0].ulValueLen++; + objects = find_objects(token, sessionOpt, + email_template, etsize, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *id, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE id_template[3]; + CK_ULONG idtsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(id_template, attr, idtsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(id_template, attr, idtsize); + /* now locate the token certs matching this template */ + objects = find_objects_by_template(token, sessionOpt, + id_template, idtsize, + maximumOpt, statusOpt); + return objects; +} + +/* + * decode the serial item and return our result. + * NOTE serialDecode's data is really stored in serial. Don't free it. + */ +static PRStatus +nssToken_decodeSerialItem(NSSItem *serial, NSSItem *serialDecode) +{ + unsigned char *data = (unsigned char *)serial->data; + int data_left, data_len, index; + + if ((serial->size >= 3) && (data[0] == 0x2)) { + /* remove the der encoding of the serial number before generating the + * key.. */ + data_left = serial->size-2; + data_len = data[1]; + index = 2; + + /* extended length ? (not very likely for a serial number) */ + if (data_len & 0x80) { + int len_count = data_len & 0x7f; + + data_len = 0; + data_left -= len_count; + if (data_left > 0) { + while (len_count --) { + data_len = (data_len << 8) | data[index++]; + } + } + } + /* XXX leaving any leading zeros on the serial number for backwards + * compatibility + */ + /* not a valid der, must be just an unlucky serial number value */ + if (data_len == data_left) { + serialDecode->size = data_len; + serialDecode->data = &data[index]; + return PR_SUCCESS; + } + } + return PR_FAILURE; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindCertificateByIssuerAndSerialNumber +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *issuer, + NSSDER *serial, + nssTokenSearchType searchType, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE_PTR serialAttr; + CK_ATTRIBUTE cert_template[4]; + CK_ULONG ctsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvObject = NULL; + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + /* Set the unique id */ + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); + serialAttr = attr; + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); + /* get the object handle */ + objects = find_objects_by_template(token, sessionOpt, + cert_template, ctsize, + 1, statusOpt); + if (objects) { + rvObject = objects[0]; + nss_ZFreeIf(objects); + } + + /* + * NSS used to incorrectly store serial numbers in their decoded form. + * because of this old tokens have decoded serial numbers. + */ + if (!objects) { + NSSItem serialDecode; + PRStatus status; + + status = nssToken_decodeSerialItem(serial, &serialDecode); + if (status != PR_SUCCESS) { + return NULL; + } + NSS_CK_SET_ATTRIBUTE_ITEM(serialAttr,CKA_SERIAL_NUMBER,&serialDecode); + objects = find_objects_by_template(token, sessionOpt, + cert_template, ctsize, + 1, statusOpt); + if (objects) { + rvObject = objects[0]; + nss_ZFreeIf(objects); + } + } + return rvObject; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindCertificateByEncodedCertificate +( + NSSToken *token, + nssSession *sessionOpt, + NSSBER *encodedCertificate, + nssTokenSearchType searchType, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[3]; + CK_ULONG ctsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvObject = NULL; + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate); + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); + /* get the object handle */ + objects = find_objects_by_template(token, sessionOpt, + cert_template, ctsize, + 1, statusOpt); + if (objects) { + rvObject = objects[0]; + nss_ZFreeIf(objects); + } + return rvObject; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindPrivateKeys +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[2]; + CK_ULONG ktsize; + nssCryptokiObject **objects; + + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); + + objects = find_objects_by_template(token, sessionOpt, + key_template, ktsize, + maximumOpt, statusOpt); + return objects; +} + +/* XXX ?there are no session cert objects, so only search token objects */ +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindPrivateKeyByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *keyID +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[3]; + CK_ULONG ktsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvKey = NULL; + + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); + + objects = find_objects_by_template(token, sessionOpt, + key_template, ktsize, + 1, NULL); + if (objects) { + rvKey = objects[0]; + nss_ZFreeIf(objects); + } + return rvKey; +} + +/* XXX ?there are no session cert objects, so only search token objects */ +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindPublicKeyByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *keyID +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[3]; + CK_ULONG ktsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvKey = NULL; + + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); + + objects = find_objects_by_template(token, sessionOpt, + key_template, ktsize, + 1, NULL); + if (objects) { + rvKey = objects[0]; + nss_ZFreeIf(objects); + } + return rvKey; +} + +static void +sha1_hash(NSSItem *input, NSSItem *output) +{ + NSSAlgorithmAndParameters *ap; +#ifdef NSS_3_4_CODE + PK11SlotInfo *internal = PK11_GetInternalSlot(); + NSSToken *token = PK11Slot_GetNSSToken(internal); +#else + NSSToken *token = nss_GetDefaultCryptoToken(); +#endif + ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL); + (void)nssToken_Digest(token, NULL, ap, input, output, NULL); +#ifdef NSS_3_4_CODE + PK11_FreeSlot(token->pk11slot); +#endif + nss_ZFreeIf(ap); +} + +static void +md5_hash(NSSItem *input, NSSItem *output) +{ + NSSAlgorithmAndParameters *ap; +#ifdef NSS_3_4_CODE + PK11SlotInfo *internal = PK11_GetInternalSlot(); + NSSToken *token = PK11Slot_GetNSSToken(internal); +#else + NSSToken *token = nss_GetDefaultCryptoToken(); +#endif + ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL); + (void)nssToken_Digest(token, NULL, ap, input, output, NULL); +#ifdef NSS_3_4_CODE + PK11_FreeSlot(token->pk11slot); +#endif + nss_ZFreeIf(ap); +} + +static CK_TRUST +get_ck_trust +( + nssTrustLevel nssTrust +) +{ + CK_TRUST t; + switch (nssTrust) { + case nssTrustLevel_Unknown: t = CKT_NETSCAPE_TRUST_UNKNOWN; break; + case nssTrustLevel_NotTrusted: t = CKT_NETSCAPE_UNTRUSTED; break; + case nssTrustLevel_TrustedDelegator: t = CKT_NETSCAPE_TRUSTED_DELEGATOR; + break; + case nssTrustLevel_ValidDelegator: t = CKT_NETSCAPE_VALID_DELEGATOR; break; + case nssTrustLevel_Trusted: t = CKT_NETSCAPE_TRUSTED; break; + case nssTrustLevel_Valid: t = CKT_NETSCAPE_VALID; break; + } + return t; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_ImportTrust +( + NSSToken *tok, + nssSession *sessionOpt, + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTrustLevel serverAuth, + nssTrustLevel clientAuth, + nssTrustLevel codeSigning, + nssTrustLevel emailProtection, + PRBool asTokenObject +) +{ + nssCryptokiObject *object; + CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; + CK_TRUST ckSA, ckCA, ckCS, ckEP; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE trust_tmpl[10]; + CK_ULONG tsize; + PRUint8 sha1[20]; /* this is cheating... */ + PRUint8 md5[16]; + NSSItem sha1_result, md5_result; + sha1_result.data = sha1; sha1_result.size = sizeof sha1; + md5_result.data = md5; md5_result.size = sizeof md5; + sha1_hash(certEncoding, &sha1_result); + md5_hash(certEncoding, &md5_result); + ckSA = get_ck_trust(serverAuth); + ckCA = get_ck_trust(clientAuth); + ckCS = get_ck_trust(codeSigning); + ckEP = get_ck_trust(emailProtection); + NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize); + if (asTokenObject) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, certSerial); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH, &md5_result); + /* now set the trust values */ + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, ckSA); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, ckCA); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, ckCS); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP); + NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize); + /* import the trust object onto the token */ + object = import_object(tok, sessionOpt, trust_tmpl, tsize); + if (object && tok->cache) { + nssTokenObjectCache_ImportObject(tok->cache, object, tobjc, + trust_tmpl, tsize); + } + return object; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindTrustObjects +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE tobj_template[2]; + CK_ULONG tobj_size; + nssCryptokiObject **objects; + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; + + NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); + NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); + + if (searchType == nssTokenSearchType_TokenForced) { + objects = find_objects(token, session, + tobj_template, tobj_size, + maximumOpt, statusOpt); + } else { + objects = find_objects_by_template(token, session, + tobj_template, tobj_size, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindTrustForCertificate +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTokenSearchType searchType +) +{ + CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE tobj_template[5]; + CK_ULONG tobj_size; + PRUint8 sha1[20]; /* this is cheating... */ + NSSItem sha1_result; + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; + nssCryptokiObject *object, **objects; + + sha1_result.data = sha1; sha1_result.size = sizeof sha1; + sha1_hash(certEncoding, &sha1_result); + NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); +#ifdef NSS_3_4_CODE + if (!PK11_HasRootCerts(token->pk11slot)) { +#endif + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial); +#ifdef NSS_3_4_CODE + } + /* + * we need to arrange for the built-in token to lose the bottom 2 + * attributes so that old built-in tokens will continue to work. + */ +#endif + NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); + object = NULL; + objects = find_objects_by_template(token, session, + tobj_template, tobj_size, + 1, NULL); + if (objects) { + object = objects[0]; + nss_ZFreeIf(objects); + } + return object; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_ImportCRL +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + NSSDER *encoding, + PRBool isKRL, + NSSUTF8 *url, + PRBool asTokenObject +) +{ + nssCryptokiObject *object; + CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE crl_tmpl[6]; + CK_ULONG crlsize; + + NSS_CK_TEMPLATE_START(crl_tmpl, attr, crlsize); + if (asTokenObject) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_URL, url); + if (isKRL) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NETSCAPE_KRL, &g_ck_true); + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NETSCAPE_KRL, &g_ck_false); + } + NSS_CK_TEMPLATE_FINISH(crl_tmpl, attr, crlsize); + + /* import the crl object onto the token */ + object = import_object(token, sessionOpt, crl_tmpl, crlsize); + if (object && token->cache) { + nssTokenObjectCache_ImportObject(token->cache, object, crlobjc, + crl_tmpl, crlsize); + } + return object; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCRLs +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE crlobj_template[2]; + CK_ULONG crlobj_size; + nssCryptokiObject **objects; + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; + + NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); + NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size); + + if (searchType == nssTokenSearchType_TokenForced) { + objects = find_objects(token, session, + crlobj_template, crlobj_size, + maximumOpt, statusOpt); + } else { + objects = find_objects_by_template(token, session, + crlobj_template, crlobj_size, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCRLsBySubject +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE crlobj_template[3]; + CK_ULONG crlobj_size; + nssCryptokiObject **objects; + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; + + NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size); + + objects = find_objects_by_template(token, session, + crlobj_template, crlobj_size, + maximumOpt, statusOpt); + return objects; } NSS_IMPLEMENT PRStatus -nssToken_SetHasCrls +nssToken_GetCachedObjectAttributes ( - NSSToken *tok + NSSToken *token, + NSSArena *arenaOpt, + nssCryptokiObject *object, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR atemplate, + CK_ULONG atlen ) { - tok->hasNoCrls = PR_FALSE; - return PR_SUCCESS; + if (!token->cache) { + return PR_FAILURE; + } + return nssTokenObjectCache_GetObjectAttributes(token->cache, arenaOpt, + object, objclass, + atemplate, atlen); } NSS_IMPLEMENT NSSItem * @@ -315,17 +1399,18 @@ nssToken_Digest CK_ULONG digestLen; CK_BYTE_PTR digest; NSSItem *rvItem = NULL; + void *epv = nssToken_GetCryptokiEPV(tok); nssSession *session; session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism); + ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); return NULL; } #if 0 /* XXX the standard says this should work, but it doesn't */ - ckrv = CKAPI(tok)->C_Digest(session->handle, NULL, 0, NULL, &digestLen); + ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); return NULL; @@ -351,7 +1436,7 @@ nssToken_Digest return NULL; } } - ckrv = CKAPI(tok)->C_Digest(session->handle, + ckrv = CKAPI(epv)->C_Digest(session->handle, (CK_BYTE_PTR)data->data, (CK_ULONG)data->size, (CK_BYTE_PTR)digest, @@ -377,9 +1462,10 @@ nssToken_BeginDigest { CK_RV ckrv; nssSession *session; + void *epv = nssToken_GetCryptokiEPV(tok); session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism); + ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); nssSession_ExitMonitor(session); return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; } @@ -394,9 +1480,10 @@ nssToken_ContinueDigest { CK_RV ckrv; nssSession *session; + void *epv = nssToken_GetCryptokiEPV(tok); session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestUpdate(session->handle, + ckrv = CKAPI(epv)->C_DigestUpdate(session->handle, (CK_BYTE_PTR)item->data, (CK_ULONG)item->size); nssSession_ExitMonitor(session); @@ -416,10 +1503,11 @@ nssToken_FinishDigest CK_ULONG digestLen; CK_BYTE_PTR digest; NSSItem *rvItem = NULL; + void *epv = nssToken_GetCryptokiEPV(tok); nssSession *session; session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestFinal(session->handle, NULL, &digestLen); + ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen); if (ckrv != CKR_OK || digestLen == 0) { nssSession_ExitMonitor(session); return NULL; @@ -443,7 +1531,7 @@ nssToken_FinishDigest return NULL; } } - ckrv = CKAPI(tok)->C_DigestFinal(session->handle, digest, &digestLen); + ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { nss_ZFreeIf(digest); @@ -455,36 +1543,122 @@ nssToken_FinishDigest return rvItem; } -/* XXX of course this doesn't belong here */ -NSS_IMPLEMENT NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateSHA1Digest +NSS_IMPLEMENT PRBool +nssToken_IsPresent ( - NSSArena *arenaOpt + NSSToken *token ) { - NSSAlgorithmAndParameters *rvAP = NULL; - rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); - if (rvAP) { - rvAP->mechanism.mechanism = CKM_SHA_1; - rvAP->mechanism.pParameter = NULL; - rvAP->mechanism.ulParameterLen = 0; - } - return rvAP; + return nssSlot_IsTokenPresent(token->slot); } -NSS_IMPLEMENT NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateMD5Digest +/* Sigh. The methods to find objects declared above cause problems with + * the low-level object cache in the softoken -- the objects are found in + * toto, then one wave of GetAttributes is done, then another. Having a + * large number of objects causes the cache to be thrashed, as the objects + * are gone before there's any chance to ask for their attributes. + * So, for now, bringing back traversal methods for certs. This way all of + * the cert's attributes can be grabbed immediately after finding it, + * increasing the likelihood that the cache takes care of it. + */ +NSS_IMPLEMENT PRStatus +nssToken_TraverseCertificates ( - NSSArena *arenaOpt + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRStatus (* callback)(nssCryptokiObject *instance, void *arg), + void *arg ) { - NSSAlgorithmAndParameters *rvAP = NULL; - rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); - if (rvAP) { - rvAP->mechanism.mechanism = CKM_MD5; - rvAP->mechanism.pParameter = NULL; - rvAP->mechanism.ulParameterLen = 0; + CK_RV ckrv; + CK_ULONG count; + CK_OBJECT_HANDLE *objectHandles; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[2]; + CK_ULONG ctsize; + NSSArena *arena; + PRStatus status; + PRUint32 arraySize, numHandles; + nssCryptokiObject **objects; + void *epv = nssToken_GetCryptokiEPV(token); + nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession; + + /* template for all certs */ + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); + + /* the arena is only for the array of object handles */ + arena = nssArena_Create(); + if (!arena) { + return PR_FAILURE; } - return rvAP; + arraySize = OBJECT_STACK_SIZE; + numHandles = 0; + objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize); + if (!objectHandles) { + goto loser; + } + nssSession_EnterMonitor(session); /* ==== session lock === */ + /* Initialize the find with the template */ + ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, + cert_template, ctsize); + if (ckrv != CKR_OK) { + nssSession_ExitMonitor(session); + goto loser; + } + while (PR_TRUE) { + /* Issue the find for up to arraySize - numHandles objects */ + ckrv = CKAPI(epv)->C_FindObjects(session->handle, + objectHandles + numHandles, + arraySize - numHandles, + &count); + if (ckrv != CKR_OK) { + nssSession_ExitMonitor(session); + goto loser; + } + /* bump the number of found objects */ + numHandles += count; + if (numHandles < arraySize) { + break; + } + /* the array is filled, double it and continue */ + arraySize *= 2; + objectHandles = nss_ZREALLOCARRAY(objectHandles, + CK_OBJECT_HANDLE, + arraySize); + if (!objectHandles) { + nssSession_ExitMonitor(session); + goto loser; + } + } + ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); + nssSession_ExitMonitor(session); /* ==== end session lock === */ + if (ckrv != CKR_OK) { + goto loser; + } + if (numHandles > 0) { + objects = create_objects_from_handles(token, session, + objectHandles, numHandles); + if (objects) { + nssCryptokiObject **op; + for (op = objects; *op; op++) { + status = (*callback)(*op, arg); + } + nss_ZFreeIf(objects); + } + } + nssArena_Destroy(arena); + return PR_SUCCESS; +loser: + nssArena_Destroy(arena); + return PR_FAILURE; } diff --git a/security/nss/lib/dev/devutil.c b/security/nss/lib/dev/devutil.c index 02db7831b..99218f83d 100644 --- a/security/nss/lib/dev/devutil.c +++ b/security/nss/lib/dev/devutil.c @@ -39,14 +39,1407 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "devm.h" #endif /* DEVM_H */ +#ifndef CKHELPER_H +#include "ckhelper.h" +#endif /* CKHELPER_H */ + +NSS_IMPLEMENT nssCryptokiObject * +nssCryptokiObject_Create +( + NSSToken *t, + nssSession *session, + CK_OBJECT_HANDLE h +) +{ + PRStatus status; + NSSSlot *slot; + nssCryptokiObject *object; + CK_BBOOL *isTokenObject; + CK_ATTRIBUTE cert_template[] = { + { CKA_TOKEN, NULL, 0 }, + { CKA_LABEL, NULL, 0 } + }; + slot = nssToken_GetSlot(t); + status = nssCKObject_GetAttributes(h, cert_template, 2, + NULL, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + /* a failure here indicates a device error */ + return (nssCryptokiObject *)NULL; + } + object = nss_ZNEW(NULL, nssCryptokiObject); + if (!object) { + return (nssCryptokiObject *)NULL; + } + object->handle = h; + object->token = nssToken_AddRef(t); + isTokenObject = (CK_BBOOL *)cert_template[0].pValue; + object->isTokenObject = *isTokenObject; + nss_ZFreeIf(isTokenObject); + NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[1], object->label); + return object; +} + +NSS_IMPLEMENT void +nssCryptokiObject_Destroy +( + nssCryptokiObject *object +) +{ + if (object) { + nssToken_Destroy(object->token); + nss_ZFreeIf(object->label); + nss_ZFreeIf(object); + } +} + +NSS_IMPLEMENT nssCryptokiObject * +nssCryptokiObject_Clone +( + nssCryptokiObject *object +) +{ + nssCryptokiObject *rvObject; + rvObject = nss_ZNEW(NULL, nssCryptokiObject); + if (rvObject) { + rvObject->handle = object->handle; + rvObject->token = nssToken_AddRef(object->token); + rvObject->isTokenObject = object->isTokenObject; + if (object->label) { + rvObject->label = nssUTF8_Duplicate(object->label, NULL); + } + } + return rvObject; +} + +NSS_EXTERN PRBool +nssCryptokiObject_Equal +( + nssCryptokiObject *o1, + nssCryptokiObject *o2 +) +{ + return (o1->token == o2->token && o1->handle == o2->handle); +} + NSS_IMPLEMENT PRUint32 -nssPKCS11StringLength(CK_CHAR *pkcs11Str, PRUint32 bufLen) +nssPKCS11String_Length(CK_CHAR *pkcs11Str, PRUint32 bufLen) { PRInt32 i; for (i = bufLen - 1; i>=0; ) { - if (pkcs11Str[i] != ' ') break; + if (pkcs11Str[i] != ' ' && pkcs11Str[i] != '\0') break; --i; } return (PRUint32)(i + 1); } +/* + * Slot arrays + */ + +NSS_IMPLEMENT NSSSlot ** +nssSlotArray_Clone +( + NSSSlot **slots +) +{ + NSSSlot **rvSlots = NULL; + NSSSlot **sp = slots; + PRUint32 count = 0; + while (sp && *sp) count++; + if (count > 0) { + rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1); + if (rvSlots) { + sp = slots; + count = 0; + for (sp = slots; *sp; sp++) { + rvSlots[count++] = nssSlot_AddRef(*sp); + } + } + } + return rvSlots; +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT void +nssModuleArray_Destroy +( + NSSModule **modules +) +{ + if (modules) { + NSSModule **mp; + for (mp = modules; *mp; mp++) { + nssModule_Destroy(*mp); + } + nss_ZFreeIf(modules); + } +} +#endif + +NSS_IMPLEMENT void +nssSlotArray_Destroy +( + NSSSlot **slots +) +{ + if (slots) { + NSSSlot **slotp; + for (slotp = slots; *slotp; slotp++) { + nssSlot_Destroy(*slotp); + } + nss_ZFreeIf(slots); + } +} + +NSS_IMPLEMENT void +NSSSlotArray_Destroy +( + NSSSlot **slots +) +{ + nssSlotArray_Destroy(slots); +} + +NSS_IMPLEMENT void +nssTokenArray_Destroy +( + NSSToken **tokens +) +{ + if (tokens) { + NSSToken **tokenp; + for (tokenp = tokens; *tokenp; tokenp++) { + nssToken_Destroy(*tokenp); + } + nss_ZFreeIf(tokens); + } +} + +NSS_IMPLEMENT void +NSSTokenArray_Destroy +( + NSSToken **tokens +) +{ + nssTokenArray_Destroy(tokens); +} + +NSS_IMPLEMENT void +nssCryptokiObjectArray_Destroy +( + nssCryptokiObject **objects +) +{ + if (objects) { + nssCryptokiObject **op; + for (op = objects; *op; op++) { + nssCryptokiObject_Destroy(*op); + } + nss_ZFreeIf(objects); + } +} + +#ifdef PURE_STAN_BUILD +/* + * Slot lists + */ + +struct nssSlotListNodeStr +{ + PRCList link; + NSSSlot *slot; + PRUint32 order; +}; + +/* XXX separate slots with non-present tokens? */ +struct nssSlotListStr +{ + NSSArena *arena; + PRBool i_allocated_arena; + PZLock *lock; + PRCList head; + PRUint32 count; +}; + +NSS_IMPLEMENT nssSlotList * +nssSlotList_Create +( + NSSArena *arenaOpt +) +{ + nssSlotList *rvList; + NSSArena *arena; + nssArenaMark *mark; + if (arenaOpt) { + arena = arenaOpt; + mark = nssArena_Mark(arena); + if (!mark) { + return (nssSlotList *)NULL; + } + } else { + arena = nssArena_Create(); + if (!arena) { + return (nssSlotList *)NULL; + } + } + rvList = nss_ZNEW(arena, nssSlotList); + if (!rvList) { + goto loser; + } + rvList->lock = PZ_NewLock(nssILockOther); /* XXX */ + if (!rvList->lock) { + goto loser; + } + PR_INIT_CLIST(&rvList->head); + rvList->arena = arena; + rvList->i_allocated_arena = (arenaOpt == NULL); + nssArena_Unmark(arena, mark); + return rvList; +loser: + if (arenaOpt) { + nssArena_Release(arena, mark); + } else { + nssArena_Destroy(arena); + } + return (nssSlotList *)NULL; +} + +NSS_IMPLEMENT void +nssSlotList_Destroy +( + nssSlotList *slotList +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + if (slotList) { + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + nssSlot_Destroy(node->slot); + link = PR_NEXT_LINK(link); + } + if (slotList->i_allocated_arena) { + nssArena_Destroy(slotList->arena); + } + } +} + +/* XXX should do allocs outside of lock */ +NSS_IMPLEMENT PRStatus +nssSlotList_Add +( + nssSlotList *slotList, + NSSSlot *slot, + PRUint32 order +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + if (order < node->order) { + break; + } + link = PR_NEXT_LINK(link); + } + node = nss_ZNEW(slotList->arena, struct nssSlotListNodeStr); + if (!node) { + return PR_FAILURE; + } + PR_INIT_CLIST(&node->link); + node->slot = nssSlot_AddRef(slot); + node->order = order; + PR_INSERT_AFTER(&node->link, link); + slotList->count++; + PZ_Unlock(slotList->lock); + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssSlotList_AddModuleSlots +( + nssSlotList *slotList, + NSSModule *module, + PRUint32 order +) +{ + nssArenaMark *mark = NULL; + NSSSlot **sp, **slots = NULL; + PRCList *link; + struct nssSlotListNodeStr *node; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + if (order < node->order) { + break; + } + link = PR_NEXT_LINK(link); + } + slots = nssModule_GetSlots(module); + if (!slots) { + PZ_Unlock(slotList->lock); + return PR_SUCCESS; + } + mark = nssArena_Mark(slotList->arena); + if (!mark) { + goto loser; + } + for (sp = slots; *sp; sp++) { + node = nss_ZNEW(slotList->arena, struct nssSlotListNodeStr); + if (!node) { + goto loser; + } + PR_INIT_CLIST(&node->link); + node->slot = *sp; /* have ref from nssModule_GetSlots */ + node->order = order; + PR_INSERT_AFTER(&node->link, link); + slotList->count++; + } + PZ_Unlock(slotList->lock); + nssArena_Unmark(slotList->arena, mark); + return PR_SUCCESS; +loser: + PZ_Unlock(slotList->lock); + if (mark) { + nssArena_Release(slotList->arena, mark); + } + if (slots) { + nssSlotArray_Destroy(slots); + } + return PR_FAILURE; +} + +NSS_IMPLEMENT NSSSlot ** +nssSlotList_GetSlots +( + nssSlotList *slotList +) +{ + PRUint32 i; + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot **rvSlots = NULL; + PZ_Lock(slotList->lock); + rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, slotList->count + 1); + if (!rvSlots) { + PZ_Unlock(slotList->lock); + return (NSSSlot **)NULL; + } + i = 0; + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + rvSlots[i] = nssSlot_AddRef(node->slot); + link = PR_NEXT_LINK(link); + i++; + } + PZ_Unlock(slotList->lock); + return rvSlots; +} + +#if 0 +NSS_IMPLEMENT NSSSlot * +nssSlotList_GetBestSlotForAlgorithmAndParameters +( + nssSlotList *slotList, + NSSAlgorithmAndParameters *ap +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot *rvSlot = NULL; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + if (nssSlot_DoesAlgorithmAndParameters(ap)) { + rvSlot = nssSlot_AddRef(node->slot); /* XXX check isPresent? */ + } + link = PR_NEXT_LINK(link); + } + PZ_Unlock(slotList->lock); + return rvSlot; +} +#endif + +NSS_IMPLEMENT NSSSlot * +nssSlotList_GetBestSlot +( + nssSlotList *slotList +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot *rvSlot = NULL; + PZ_Lock(slotList->lock); + if (PR_CLIST_IS_EMPTY(&slotList->head)) { + PZ_Unlock(slotList->lock); + return (NSSSlot *)NULL; + } + link = PR_NEXT_LINK(&slotList->head); + node = (struct nssSlotListNodeStr *)link; + rvSlot = nssSlot_AddRef(node->slot); /* XXX check isPresent? */ + PZ_Unlock(slotList->lock); + return rvSlot; +} + +NSS_IMPLEMENT NSSSlot * +nssSlotList_FindSlotByName +( + nssSlotList *slotList, + NSSUTF8 *slotName +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot *rvSlot = NULL; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + NSSUTF8 *sName; + node = (struct nssSlotListNodeStr *)link; + sName = nssSlot_GetName(node->slot); + if (nssUTF8_Equal(sName, slotName, NULL)) { + rvSlot = nssSlot_AddRef(node->slot); + break; + } + link = PR_NEXT_LINK(link); + } + PZ_Unlock(slotList->lock); + return rvSlot; +} + +NSS_IMPLEMENT NSSToken * +nssSlotList_FindTokenByName +( + nssSlotList *slotList, + NSSUTF8 *tokenName +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSToken *rvToken = NULL; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + NSSUTF8 *tName; + node = (struct nssSlotListNodeStr *)link; + tName = nssSlot_GetTokenName(node->slot); + if (nssUTF8_Equal(tName, tokenName, NULL)) { + rvToken = nssSlot_GetToken(node->slot); + break; + } + link = PR_NEXT_LINK(link); + } + PZ_Unlock(slotList->lock); + return rvToken; +} +#endif /* PURE_STAN_BUILD */ + +/* object cache for token */ + +typedef struct +{ + NSSArena *arena; + nssCryptokiObject *object; + CK_ATTRIBUTE_PTR attributes; + CK_ULONG numAttributes; +} +nssCryptokiObjectAndAttributes; + +enum { + cachedCerts = 0, + cachedTrust = 1, + cachedCRLs = 2 +} cachedObjectType; + +struct nssTokenObjectCacheStr +{ + NSSToken *token; + PZLock *lock; + PRBool loggedIn; + PRBool doObjectType[3]; + PRBool searchedObjectType[3]; + nssCryptokiObjectAndAttributes **objects[3]; +}; + +NSS_IMPLEMENT nssTokenObjectCache * +nssTokenObjectCache_Create +( + NSSToken *token, + PRBool cacheCerts, + PRBool cacheTrust, + PRBool cacheCRLs +) +{ + nssTokenObjectCache *rvCache; + rvCache = nss_ZNEW(NULL, nssTokenObjectCache); + if (!rvCache) { + goto loser; + } + rvCache->lock = PZ_NewLock(nssILockOther); /* XXX */ + if (!rvCache->lock) { + goto loser; + } + rvCache->doObjectType[cachedCerts] = cacheCerts; + rvCache->doObjectType[cachedTrust] = cacheTrust; + rvCache->doObjectType[cachedCRLs] = cacheCRLs; + rvCache->token = token; /* cache goes away with token */ + return rvCache; +loser: + return (nssTokenObjectCache *)NULL; +} + +static void +clear_cache +( + nssTokenObjectCache *cache +) +{ + nssCryptokiObjectAndAttributes **oa; + PRUint32 objectType; + for (objectType = cachedCerts; objectType <= cachedCRLs; objectType++) { + if (!cache->objects[objectType]) { + continue; + } + for (oa = cache->objects[objectType]; *oa; oa++) { + /* prevent the token from being destroyed */ + (*oa)->object->token = NULL; + nssCryptokiObject_Destroy((*oa)->object); + nssArena_Destroy((*oa)->arena); + } + nss_ZFreeIf(cache->objects[objectType]); + cache->objects[objectType] = NULL; + cache->searchedObjectType[objectType] = PR_FALSE; + } +} + +NSS_IMPLEMENT void +nssTokenObjectCache_Clear +( + nssTokenObjectCache *cache +) +{ + if (cache) { + clear_cache(cache); + } +} + +NSS_IMPLEMENT void +nssTokenObjectCache_Destroy +( + nssTokenObjectCache *cache +) +{ + if (cache) { + clear_cache(cache); + PZ_DestroyLock(cache->lock); + nss_ZFreeIf(cache); + } +} + +NSS_IMPLEMENT PRBool +nssTokenObjectCache_HaveObjectClass +( + nssTokenObjectCache *cache, + CK_OBJECT_CLASS objclass +) +{ + PRBool haveIt; + PZ_Lock(cache->lock); + switch (objclass) { + case CKO_CERTIFICATE: haveIt = cache->doObjectType[cachedCerts]; break; + case CKO_NETSCAPE_TRUST: haveIt = cache->doObjectType[cachedTrust]; break; + case CKO_NETSCAPE_CRL: haveIt = cache->doObjectType[cachedCRLs]; break; + default: haveIt = PR_FALSE; + } + PZ_Unlock(cache->lock); + return haveIt; +} + +static nssCryptokiObjectAndAttributes ** +create_object_array +( + nssCryptokiObject **objects, + PRBool *doObjects, + PRUint32 *numObjects, + PRStatus *status +) +{ + nssCryptokiObject **op = objects; + nssCryptokiObjectAndAttributes **rvOandA = NULL; + *numObjects = 0; + /* There are no objects for this type */ + if (!objects) { + return (nssCryptokiObjectAndAttributes **)NULL; + } + while (*op++) (*numObjects)++; + if (*numObjects == MAX_LOCAL_CACHE_OBJECTS) { + /* Hit the maximum allowed, so don't use a cache (there are + * too many objects to make caching worthwhile, presumably, if + * the token can handle that many objects, it can handle searching. + */ + *doObjects = PR_FALSE; + *status = PR_FAILURE; + *numObjects = 0; + } else if (*numObjects > 0) { + rvOandA = nss_ZNEWARRAY(NULL, + nssCryptokiObjectAndAttributes *, + *numObjects + 1); + *status = rvOandA ? PR_SUCCESS : PR_FALSE; + } + return rvOandA; +} + +static nssCryptokiObjectAndAttributes * +create_object +( + nssCryptokiObject *object, + CK_ATTRIBUTE_TYPE *types, + PRUint32 numTypes, + PRStatus *status +) +{ + PRUint32 j; + NSSArena *arena; + NSSSlot *slot = NULL; + nssSession *session = NULL; + nssCryptokiObjectAndAttributes *rvCachedObject = NULL; + + slot = nssToken_GetSlot(object->token); + session = nssToken_GetDefaultSession(object->token); + + arena = nssArena_Create(); + if (!arena) { + nssSlot_Destroy(slot); + return (nssCryptokiObjectAndAttributes *)NULL; + } + rvCachedObject = nss_ZNEW(arena, nssCryptokiObjectAndAttributes); + if (!rvCachedObject) { + goto loser; + } + rvCachedObject->arena = arena; + /* The cache is tied to the token, and therefore the objects + * in it should not hold references to the token. + */ + nssToken_Destroy(object->token); + rvCachedObject->object = object; + rvCachedObject->attributes = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, numTypes); + if (!rvCachedObject->attributes) { + goto loser; + } + for (j=0; j<numTypes; j++) { + rvCachedObject->attributes[j].type = types[j]; + } + *status = nssCKObject_GetAttributes(object->handle, + rvCachedObject->attributes, + numTypes, + arena, + session, + slot); + if (*status != PR_SUCCESS) { + goto loser; + } + rvCachedObject->numAttributes = numTypes; + *status = PR_SUCCESS; + if (slot) { + nssSlot_Destroy(slot); + } + return rvCachedObject; +loser: + *status = PR_FAILURE; + if (slot) { + nssSlot_Destroy(slot); + } + nssArena_Destroy(arena); + return (nssCryptokiObjectAndAttributes *)NULL; +} + +/* + * + * State diagram for cache: + * + * token !present token removed + * +-------------------------+<----------------------+ + * | ^ | + * v | | + * +----------+ slot friendly | token present +----------+ + * | cache | -----------------> % ---------------> | cache | + * | unloaded | | loaded | + * +----------+ +----------+ + * ^ | ^ | + * | | slot !friendly slot logged in | | + * | +-----------------------> % ----------------------+ | + * | | | + * | slot logged out v slot !friendly | + * +-----------------------------+<--------------------------+ + * + */ +static PRBool +search_for_objects +( + nssTokenObjectCache *cache +) +{ + PRBool doSearch = PR_FALSE; + NSSSlot *slot = nssToken_GetSlot(cache->token); + if (!nssSlot_IsTokenPresent(slot)) { + /* The token is no longer present, destroy any cached objects */ + /* clear_cache(cache); */ + nssSlot_Destroy(slot); + return PR_FALSE; + } + /* Handle non-friendly slots (slots which require login for objects) */ + if (!nssSlot_IsFriendly(slot)) { + if (nssSlot_IsLoggedIn(slot)) { + /* Either no state change, or went from !logged in -> logged in */ + cache->loggedIn = PR_TRUE; + doSearch = PR_TRUE; + } else { + if (cache->loggedIn) { + /* went from logged in -> !logged in, destroy cached objects */ + clear_cache(cache); + cache->loggedIn = PR_FALSE; + } /* else no state change, still not logged in, so exit */ + } + } else { + /* slot is friendly, thus always available for search */ + doSearch = PR_TRUE; + } + nssSlot_Destroy(slot); + return doSearch; +} + +static nssCryptokiObjectAndAttributes * +create_cert +( + nssCryptokiObject *object, + PRStatus *status +) +{ + CK_ATTRIBUTE_TYPE certAttr[] = { + CKA_CLASS, + CKA_TOKEN, + CKA_LABEL, + CKA_CERTIFICATE_TYPE, + CKA_ID, + CKA_VALUE, + CKA_ISSUER, + CKA_SERIAL_NUMBER, + CKA_SUBJECT, + CKA_NETSCAPE_EMAIL + }; + PRUint32 numCertAttr = sizeof(certAttr) / sizeof(certAttr[0]); + return create_object(object, certAttr, numCertAttr, status); +} + +static PRStatus +get_token_certs_for_cache +( + nssTokenObjectCache *cache +) +{ + PRStatus status; + nssCryptokiObject **objects; + PRBool *doIt = &cache->doObjectType[cachedCerts]; + PRUint32 i, numObjects; + + if (!search_for_objects(cache) || + cache->searchedObjectType[cachedCerts] || + !cache->doObjectType[cachedCerts]) + { + /* Either there was a state change that prevents a search + * (token removed or logged out), or the search was already done, + * or certs are not being cached. + */ + return PR_SUCCESS; + } + objects = nssToken_FindCertificates(cache->token, NULL, + nssTokenSearchType_TokenForced, + MAX_LOCAL_CACHE_OBJECTS, &status); + if (status != PR_SUCCESS) { + return status; + } + cache->objects[cachedCerts] = create_object_array(objects, + doIt, + &numObjects, + &status); + if (status != PR_SUCCESS) { + return status; + } + for (i=0; i<numObjects; i++) { + cache->objects[cachedCerts][i] = create_cert(objects[i], &status); + if (status != PR_SUCCESS) { + break; + } + } + if (status == PR_SUCCESS) { + nss_ZFreeIf(objects); + } else { + PRUint32 j; + for (j=0; j<i; j++) { + /* sigh */ + nssToken_AddRef(cache->objects[cachedCerts][i]->object->token); + nssArena_Destroy(cache->objects[cachedCerts][i]->arena); + } + nssCryptokiObjectArray_Destroy(objects); + } + cache->searchedObjectType[cachedCerts] = PR_TRUE; + return status; +} + +static nssCryptokiObjectAndAttributes * +create_trust +( + nssCryptokiObject *object, + PRStatus *status +) +{ + CK_ATTRIBUTE_TYPE trustAttr[] = { + CKA_CLASS, + CKA_TOKEN, + CKA_LABEL, + CKA_CERT_SHA1_HASH, + CKA_CERT_MD5_HASH, + CKA_ISSUER, + CKA_SUBJECT, + CKA_TRUST_SERVER_AUTH, + CKA_TRUST_CLIENT_AUTH, + CKA_TRUST_EMAIL_PROTECTION, + CKA_TRUST_CODE_SIGNING + }; + PRUint32 numTrustAttr = sizeof(trustAttr) / sizeof(trustAttr[0]); + return create_object(object, trustAttr, numTrustAttr, status); +} + +static PRStatus +get_token_trust_for_cache +( + nssTokenObjectCache *cache +) +{ + PRStatus status; + nssCryptokiObject **objects; + PRBool *doIt = &cache->doObjectType[cachedTrust]; + PRUint32 i, numObjects; + + if (!search_for_objects(cache) || + cache->searchedObjectType[cachedTrust] || + !cache->doObjectType[cachedTrust]) + { + /* Either there was a state change that prevents a search + * (token removed or logged out), or the search was already done, + * or trust is not being cached. + */ + return PR_SUCCESS; + } + objects = nssToken_FindTrustObjects(cache->token, NULL, + nssTokenSearchType_TokenForced, + MAX_LOCAL_CACHE_OBJECTS, &status); + if (status != PR_SUCCESS) { + return status; + } + cache->objects[cachedTrust] = create_object_array(objects, + doIt, + &numObjects, + &status); + if (status != PR_SUCCESS) { + return status; + } + for (i=0; i<numObjects; i++) { + cache->objects[cachedTrust][i] = create_trust(objects[i], &status); + if (status != PR_SUCCESS) { + break; + } + } + if (status == PR_SUCCESS) { + nss_ZFreeIf(objects); + } else { + PRUint32 j; + for (j=0; j<i; j++) { + /* sigh */ + nssToken_AddRef(cache->objects[cachedTrust][i]->object->token); + nssArena_Destroy(cache->objects[cachedTrust][i]->arena); + } + nssCryptokiObjectArray_Destroy(objects); + } + cache->searchedObjectType[cachedTrust] = PR_TRUE; + return status; +} + +static nssCryptokiObjectAndAttributes * +create_crl +( + nssCryptokiObject *object, + PRStatus *status +) +{ + CK_ATTRIBUTE_TYPE crlAttr[] = { + CKA_CLASS, + CKA_TOKEN, + CKA_LABEL, + CKA_VALUE, + CKA_SUBJECT, + CKA_NETSCAPE_KRL, + CKA_NETSCAPE_URL + }; + PRUint32 numCRLAttr = sizeof(crlAttr) / sizeof(crlAttr[0]); + return create_object(object, crlAttr, numCRLAttr, status); +} + +static PRStatus +get_token_crls_for_cache +( + nssTokenObjectCache *cache +) +{ + PRStatus status; + nssCryptokiObject **objects; + PRBool *doIt = &cache->doObjectType[cachedCRLs]; + PRUint32 i, numObjects; + + if (!search_for_objects(cache) || + cache->searchedObjectType[cachedCRLs] || + !cache->doObjectType[cachedCRLs]) + { + /* Either there was a state change that prevents a search + * (token removed or logged out), or the search was already done, + * or CRLs are not being cached. + */ + return PR_SUCCESS; + } + objects = nssToken_FindCRLs(cache->token, NULL, + nssTokenSearchType_TokenForced, + MAX_LOCAL_CACHE_OBJECTS, &status); + if (status != PR_SUCCESS) { + return status; + } + cache->objects[cachedCRLs] = create_object_array(objects, + doIt, + &numObjects, + &status); + if (status != PR_SUCCESS) { + return status; + } + for (i=0; i<numObjects; i++) { + cache->objects[cachedCRLs][i] = create_crl(objects[i], &status); + if (status != PR_SUCCESS) { + break; + } + } + if (status == PR_SUCCESS) { + nss_ZFreeIf(objects); + } else { + PRUint32 j; + for (j=0; j<i; j++) { + /* sigh */ + nssToken_AddRef(cache->objects[cachedCRLs][i]->object->token); + nssArena_Destroy(cache->objects[cachedCRLs][i]->arena); + } + nssCryptokiObjectArray_Destroy(objects); + } + cache->searchedObjectType[cachedCRLs] = PR_TRUE; + return status; +} + +static nssCryptokiObject ** +find_objects_in_array +( + nssCryptokiObjectAndAttributes **objArray, + CK_ATTRIBUTE_PTR ot, + CK_ULONG otlen, + PRUint32 maximumOpt +) +{ + PRIntn oi; + PRUint32 i, j; + PRBool match; + NSSArena *arena; + PRUint32 size = 8; + PRUint32 numMatches = 0; + nssCryptokiObject **objects = NULL; + nssCryptokiObjectAndAttributes **matches = NULL; + if (!objArray) { + return (nssCryptokiObject **)NULL; + } + arena = nssArena_Create(); + if (!arena) { + return (nssCryptokiObject **)NULL; + } + matches = nss_ZNEWARRAY(arena, nssCryptokiObjectAndAttributes *, size); + if (!matches) { + goto loser; + } + if (maximumOpt == 0) maximumOpt = ~0; + for (; *objArray && numMatches < maximumOpt; objArray++) { + nssCryptokiObjectAndAttributes *obj = *objArray; + for (i=0; i<otlen; i++) { + for (j=0; j<obj->numAttributes; j++) { + if (ot[i].type == obj->attributes[j].type) { + if (ot[i].ulValueLen == obj->attributes[j].ulValueLen && + nsslibc_memequal(ot[i].pValue, + obj->attributes[j].pValue, + ot[i].ulValueLen, NULL)) + { + match = PR_TRUE; + } else { + match = PR_FALSE; + } + break; + } + } + if (j == obj->numAttributes || !match) { + break; + } + } + if (match) { + matches[numMatches++] = obj; + if (numMatches == size) { + size *= 2; + matches = nss_ZREALLOCARRAY(matches, + nssCryptokiObjectAndAttributes *, + size); + if (!matches) { + goto loser; + } + } + } + } + if (numMatches > 0) { + objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numMatches + 1); + if (!objects) { + goto loser; + } + for (oi=0; oi<(PRIntn)numMatches; oi++) { + objects[oi] = nssCryptokiObject_Clone(matches[oi]->object); + if (!objects[oi]) { + goto loser; + } + } + } + nssArena_Destroy(arena); + return objects; +loser: + if (objects) { + for (--oi; oi>=0; --oi) { + nssCryptokiObject_Destroy(objects[oi]); + } + } + nssArena_Destroy(arena); + return (nssCryptokiObject **)NULL; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssTokenObjectCache_FindObjectsByTemplate +( + nssTokenObjectCache *cache, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR otemplate, + CK_ULONG otlen, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + PRStatus status = PR_FAILURE; + nssCryptokiObject **rvObjects = NULL; + PZ_Lock(cache->lock); + switch (objclass) { + case CKO_CERTIFICATE: + if (cache->doObjectType[cachedCerts]) { + status = get_token_certs_for_cache(cache); + if (status != PR_SUCCESS) { + goto finish; + } + rvObjects = find_objects_in_array(cache->objects[cachedCerts], + otemplate, otlen, maximumOpt); + } + break; + case CKO_NETSCAPE_TRUST: + if (cache->doObjectType[cachedTrust]) { + status = get_token_trust_for_cache(cache); + if (status != PR_SUCCESS) { + goto finish; + } + rvObjects = find_objects_in_array(cache->objects[cachedTrust], + otemplate, otlen, maximumOpt); + } + break; + case CKO_NETSCAPE_CRL: + if (cache->doObjectType[cachedCRLs]) { + status = get_token_crls_for_cache(cache); + if (status != PR_SUCCESS) { + goto finish; + } + rvObjects = find_objects_in_array(cache->objects[cachedCRLs], + otemplate, otlen, maximumOpt); + } + break; + default: break; + } +finish: + PZ_Unlock(cache->lock); + if (statusOpt) { + *statusOpt = status; + } + return rvObjects; +} + +static PRBool +cache_available_for_object_type +( + nssTokenObjectCache *cache, + PRUint32 objectType +) +{ + if (!cache->doObjectType[objectType]) { + /* not caching this object kind */ + return PR_FALSE; + } + if (!cache->searchedObjectType[objectType]) { + /* objects are not cached yet */ + return PR_FALSE; + } + if (!search_for_objects(cache)) { + /* not logged in or removed */ + return PR_FALSE; + } + return PR_TRUE; +} + +NSS_IMPLEMENT PRStatus +nssTokenObjectCache_GetObjectAttributes +( + nssTokenObjectCache *cache, + NSSArena *arenaOpt, + nssCryptokiObject *object, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR atemplate, + CK_ULONG atlen +) +{ + PRUint32 i, j; + NSSArena *arena = NULL; + nssArenaMark *mark = NULL; + nssCryptokiObjectAndAttributes *cachedOA = NULL; + nssCryptokiObjectAndAttributes **oa = NULL; + PRUint32 objectType; + PZ_Lock(cache->lock); + switch (objclass) { + case CKO_CERTIFICATE: objectType = cachedCerts; break; + case CKO_NETSCAPE_TRUST: objectType = cachedTrust; break; + case CKO_NETSCAPE_CRL: objectType = cachedCRLs; break; + default: goto loser; + } + if (!cache_available_for_object_type(cache, objectType)) { + goto loser; + } + oa = cache->objects[objectType]; + if (!oa) { + goto loser; + } + for (; *oa; oa++) { + if (nssCryptokiObject_Equal((*oa)->object, object)) { + cachedOA = *oa; + break; + } + } + if (!cachedOA) { + goto loser; /* don't have this object */ + } + if (arenaOpt) { + arena = arenaOpt; + mark = nssArena_Mark(arena); + } + for (i=0; i<atlen; i++) { + for (j=0; j<cachedOA->numAttributes; j++) { + if (atemplate[i].type == cachedOA->attributes[j].type) { + CK_ATTRIBUTE_PTR attr = &cachedOA->attributes[j]; + if (cachedOA->attributes[j].ulValueLen == 0 || + cachedOA->attributes[j].ulValueLen == (CK_ULONG)-1) + { + break; /* invalid attribute */ + } + if (atemplate[i].ulValueLen > 0) { + if (atemplate[i].pValue == NULL || + atemplate[i].ulValueLen < attr->ulValueLen) + { + goto loser; + } + } else { + atemplate[i].pValue = nss_ZAlloc(arena, attr->ulValueLen); + if (!atemplate[i].pValue) { + goto loser; + } + } + nsslibc_memcpy(atemplate[i].pValue, + attr->pValue, attr->ulValueLen); + atemplate[i].ulValueLen = attr->ulValueLen; + break; + } + } + if (j == cachedOA->numAttributes) { + atemplate[i].ulValueLen = (CK_ULONG)-1; + } + } + PZ_Unlock(cache->lock); + if (mark) { + nssArena_Unmark(arena, mark); + } + return PR_SUCCESS; +loser: + PZ_Unlock(cache->lock); + if (mark) { + nssArena_Release(arena, mark); + } + return PR_FAILURE; +} + +NSS_IMPLEMENT PRStatus +nssTokenObjectCache_ImportObject +( + nssTokenObjectCache *cache, + nssCryptokiObject *object, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR ot, + CK_ULONG otlen +) +{ + PRStatus status = PR_SUCCESS; + PRUint32 count; + nssCryptokiObjectAndAttributes **oa, ***otype; + PRUint32 objectType; + PRBool haveIt = PR_FALSE; + + PZ_Lock(cache->lock); + switch (objclass) { + case CKO_CERTIFICATE: objectType = cachedCerts; break; + case CKO_NETSCAPE_TRUST: objectType = cachedTrust; break; + case CKO_NETSCAPE_CRL: objectType = cachedCRLs; break; + default: + PZ_Unlock(cache->lock); + return PR_SUCCESS; /* don't need to import it here */ + } + if (!cache_available_for_object_type(cache, objectType)) { + PZ_Unlock(cache->lock); + return PR_SUCCESS; /* cache not active, ignored */ + } + count = 0; + otype = &cache->objects[objectType]; /* index into array of types */ + oa = *otype; /* the array of objects for this type */ + while (oa && *oa) { + if (nssCryptokiObject_Equal((*oa)->object, object)) { + haveIt = PR_TRUE; + break; + } + count++; + oa++; + } + if (haveIt) { + /* Destroy the old entry */ + (*oa)->object->token = NULL; + nssCryptokiObject_Destroy((*oa)->object); + nssArena_Destroy((*oa)->arena); + } else { + /* Create space for a new entry */ + if (count > 0) { + *otype = nss_ZREALLOCARRAY(*otype, + nssCryptokiObjectAndAttributes *, + count + 2); + } else { + *otype = nss_ZNEWARRAY(NULL, nssCryptokiObjectAndAttributes *, 2); + } + } + if (*otype) { + nssCryptokiObject *copyObject = nssCryptokiObject_Clone(object); + if (objectType == cachedCerts) { + (*otype)[count] = create_cert(copyObject, &status); + } else if (objectType == cachedTrust) { + (*otype)[count] = create_trust(copyObject, &status); + } else if (objectType == cachedCRLs) { + (*otype)[count] = create_crl(copyObject, &status); + } + } else { + status = PR_FAILURE; + } + PZ_Unlock(cache->lock); + return status; +} + +NSS_IMPLEMENT void +nssTokenObjectCache_RemoveObject +( + nssTokenObjectCache *cache, + nssCryptokiObject *object +) +{ + PRUint32 oType; + nssCryptokiObjectAndAttributes **oa, **swp = NULL; + PZ_Lock(cache->lock); + for (oType=0; oType<3; oType++) { + if (!cache_available_for_object_type(cache, oType) || + !cache->objects[oType]) + { + continue; + } + for (oa = cache->objects[oType]; *oa; oa++) { + if (nssCryptokiObject_Equal((*oa)->object, object)) { + swp = oa; /* the entry to remove */ + while (oa[1]) oa++; /* go to the tail */ + (*swp)->object->token = NULL; + nssCryptokiObject_Destroy((*swp)->object); + nssArena_Destroy((*swp)->arena); /* destroy it */ + *swp = *oa; /* swap the last with the removed */ + *oa = NULL; /* null-terminate the array */ + break; + } + } + if (swp) { + break; + } + } + if ((oType <3) && + cache->objects[oType] && cache->objects[oType][0] == NULL) { + nss_ZFreeIf(cache->objects[oType]); /* no entries remaining */ + cache->objects[oType] = NULL; + } + PZ_Unlock(cache->lock); +} + +/* XXX of course this doesn't belong here */ +NSS_IMPLEMENT NSSAlgorithmAndParameters * +NSSAlgorithmAndParameters_CreateSHA1Digest +( + NSSArena *arenaOpt +) +{ + NSSAlgorithmAndParameters *rvAP = NULL; + rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); + if (rvAP) { + rvAP->mechanism.mechanism = CKM_SHA_1; + rvAP->mechanism.pParameter = NULL; + rvAP->mechanism.ulParameterLen = 0; + } + return rvAP; +} + +NSS_IMPLEMENT NSSAlgorithmAndParameters * +NSSAlgorithmAndParameters_CreateMD5Digest +( + NSSArena *arenaOpt +) +{ + NSSAlgorithmAndParameters *rvAP = NULL; + rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); + if (rvAP) { + rvAP->mechanism.mechanism = CKM_MD5; + rvAP->mechanism.pParameter = NULL; + rvAP->mechanism.ulParameterLen = 0; + } + return rvAP; +} + diff --git a/security/nss/lib/dev/manifest.mn b/security/nss/lib/dev/manifest.mn index 46013ab5e..effab4805 100644 --- a/security/nss/lib/dev/manifest.mn +++ b/security/nss/lib/dev/manifest.mn @@ -39,6 +39,7 @@ PRIVATE_EXPORTS = \ devt.h \ dev.h \ nssdevt.h \ + nssdev.h \ $(NULL) EXPORTS = \ @@ -49,7 +50,6 @@ MODULE = security CSRCS = \ devmod.c \ devslot.c \ - devobject.c \ devtoken.c \ devutil.c \ ckhelper.c \ @@ -58,6 +58,7 @@ CSRCS = \ # here is where the 3.4 glue code is added ifndef PURE_STAN_BUILD DEFINES = -DNSS_3_4_CODE +PRIVATE_EXPORTS += devm.h devtm.h endif REQUIRES = security nspr diff --git a/security/nss/lib/fortcrypt/swfort/pkcs11/stub.c b/security/nss/lib/fortcrypt/swfort/pkcs11/stub.c index e3b854f3d..0f673e77b 100644 --- a/security/nss/lib/fortcrypt/swfort/pkcs11/stub.c +++ b/security/nss/lib/fortcrypt/swfort/pkcs11/stub.c @@ -115,6 +115,19 @@ PORT_ZFree(void *ptr, size_t len) } } +char * +PORT_Strdup(const char *str) +{ + size_t len = PORT_Strlen(str)+1; + char *newstr; + + newstr = (char *)PORT_Alloc(len); + if (newstr) { + PORT_Memcpy(newstr, str, len); + } + return newstr; +} + void PORT_SetError(int value) { @@ -210,7 +223,7 @@ PORT_ArenaUnmark(PLArenaPool *arena, void *mark) } char * -PORT_ArenaStrdup(PLArenaPool *arena,char *str) { +PORT_ArenaStrdup(PLArenaPool *arena,const char *str) { int len = PORT_Strlen(str)+1; char *newstr; diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile index eaaff9658..05cf9dc17 100644 --- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -120,6 +120,7 @@ endif endif ifeq ($(OS_TARGET), HP-UX) +ifneq ($(OS_TEST), ia64) MKSHLIB += +k +vshlibunsats -u FREEBL_GetVector +e FREEBL_GetVector ifndef FREEBL_EXTENDED_BUILD ifdef USE_PURE_32 @@ -143,6 +144,7 @@ endif endif endif endif +endif # Note: -xarch=v8 or v9 is now done in coreconf ifeq ($(OS_TARGET),SunOS) @@ -202,6 +204,7 @@ endif endif endif +$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c mac_rand.c os2_rand.c ####################################################################### # (5) Execute "global" rules. (OPTIONAL) # diff --git a/security/nss/lib/freebl/arcfour.c b/security/nss/lib/freebl/arcfour.c index 71de64b2d..23205ba73 100644 --- a/security/nss/lib/freebl/arcfour.c +++ b/security/nss/lib/freebl/arcfour.c @@ -49,6 +49,11 @@ #define USE_LONG #endif +#if defined(_WIN32_WCE) +#undef WORD +#define WORD ARC4WORD +#endif + #if defined(NSS_USE_HYBRID) && !defined(SOLARIS) && !defined(NSS_USE_64) typedef unsigned long long WORD; #else diff --git a/security/nss/lib/freebl/config.mk b/security/nss/lib/freebl/config.mk index 476e7743f..6bae7893b 100644 --- a/security/nss/lib/freebl/config.mk +++ b/security/nss/lib/freebl/config.mk @@ -37,7 +37,9 @@ ifndef FREEBL_RECURSIVE_BUILD ifndef USE_64 ifeq ($(OS_TARGET), HP-UX) - FREEBL_EXTENDED_BUILD = 1 + ifneq ($(OS_TEST), ia64) + FREEBL_EXTENDED_BUILD = 1 + endif endif ifeq ($(OS_TARGET),SunOS) diff --git a/security/nss/lib/freebl/mpi/mpi.h b/security/nss/lib/freebl/mpi/mpi.h index c44099bdd..a587c0a76 100644 --- a/security/nss/lib/freebl/mpi/mpi.h +++ b/security/nss/lib/freebl/mpi/mpi.h @@ -60,8 +60,10 @@ #undef ULLONG_MAX #endif -#ifdef macintosh +#if defined( macintosh ) #include <Types.h> +#elif defined( _WIN32_WCE) +/* #include <sys/types.h> What do we need here ?? */ #else #include <sys/types.h> #endif diff --git a/security/nss/lib/freebl/mpi/mpmontg.c b/security/nss/lib/freebl/mpi/mpmontg.c index 146c8c625..a4c5022ad 100644 --- a/security/nss/lib/freebl/mpi/mpmontg.c +++ b/security/nss/lib/freebl/mpi/mpmontg.c @@ -56,6 +56,12 @@ #define MAX_WINDOW_BITS 6 #define MAX_ODD_INTS 32 /* 2 ** (WINDOW_BITS - 1) */ +#if defined(_WIN32_WCE) +#define ABORT res = MP_UNDEF; goto CLEANUP +#else +#define ABORT abort() +#endif + typedef struct { mp_int N; /* modulus N */ mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */ @@ -272,7 +278,7 @@ mp_err mp_exptmod_f(const mp_int * montBase, } else if (smallExp & 8) { SQR; MUL(smallExp/16); SQR; SQR; SQR; } else { - abort(); + ABORT; } } else if (window_bits == 5) { if (!smallExp) { @@ -288,7 +294,7 @@ mp_err mp_exptmod_f(const mp_int * montBase, } else if (smallExp & 0x10) { SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR; } else { - abort(); + ABORT; } } else if (window_bits == 6) { if (!smallExp) { @@ -306,10 +312,10 @@ mp_err mp_exptmod_f(const mp_int * montBase, } else if (smallExp & 0x20) { SQR; MUL(smallExp/64); SQR; SQR; SQR; SQR; SQR; } else { - abort(); + ABORT; } } else { - abort(); + ABORT; } } @@ -416,7 +422,7 @@ mp_err mp_exptmod_i(const mp_int * montBase, SQR(pa1,pa2); MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else { - abort(); + ABORT; } } else if (window_bits == 5) { if (!smallExp) { @@ -438,7 +444,7 @@ mp_err mp_exptmod_i(const mp_int * montBase, SQR(pa1,pa2); MUL(smallExp/32,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); } else { - abort(); + ABORT; } } else if (window_bits == 6) { if (!smallExp) { @@ -464,10 +470,10 @@ mp_err mp_exptmod_i(const mp_int * montBase, SQR(pa1,pa2); MUL(smallExp/64,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; } else { - abort(); + ABORT; } } else { - abort(); + ABORT; } } diff --git a/security/nss/lib/freebl/rsa.c b/security/nss/lib/freebl/rsa.c index 3151ebb87..e1d973fdb 100644 --- a/security/nss/lib/freebl/rsa.c +++ b/security/nss/lib/freebl/rsa.c @@ -759,11 +759,13 @@ swap_in_key_value(PRArenaPool *arena, mp_int *mpval, SECItem *buffer) if ((unsigned int)len <= buffer->len) { /* The new value is no longer than the old buffer, so use it */ err = mp_to_unsigned_octets(mpval, buffer->data, len); + if (err >= 0) err = MP_OKAY; buffer->len = len; } else if (arena) { /* The new value is longer, but working within an arena */ (void)SECITEM_AllocItem(arena, buffer, len); err = mp_to_unsigned_octets(mpval, buffer->data, len); + if (err >= 0) err = MP_OKAY; } else { /* The new value is longer, no arena, can't handle this key */ return SECFailure; @@ -810,6 +812,7 @@ RSA_PrivateKeyCheck(RSAPrivateKey *key) /* mind the p's and q's (and d_p's and d_q's) */ SECItem tmp; mp_exch(&p, &q); + mp_exch(&d_p,&d_q); tmp = key->prime1; key->prime1 = key->prime2; key->prime2 = tmp; diff --git a/security/nss/lib/freebl/unix_rand.c b/security/nss/lib/freebl/unix_rand.c index aa64c8866..4db400655 100644 --- a/security/nss/lib/freebl/unix_rand.c +++ b/security/nss/lib/freebl/unix_rand.c @@ -180,6 +180,18 @@ GiveSystemInfo(void) #define getdtablesize() sysconf(_SC_OPEN_MAX) +#if defined(__ia64) +#include <ia64/sys/inline.h> + +static size_t +GetHighResClock(void *buf, size_t maxbytes) +{ + PRUint64 t; + + t = _Asm_mov_from_ar(_AREG44); + return CopyLowBits(buf, maxbytes, &t, sizeof(t)); +} +#else static size_t GetHighResClock(void *buf, size_t maxbytes) { @@ -189,6 +201,7 @@ GetHighResClock(void *buf, size_t maxbytes) cr16val = ret_cr16(); return CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val)); } +#endif static void GiveSystemInfo(void) diff --git a/security/nss/lib/freebl/win_rand.c b/security/nss/lib/freebl/win_rand.c index dc16b19b7..bad0365cd 100644 --- a/security/nss/lib/freebl/win_rand.c +++ b/security/nss/lib/freebl/win_rand.c @@ -34,10 +34,16 @@ #include "secrng.h" #ifdef XP_WIN #include <windows.h> + +#if defined(_WIN32_WCE) +#include <stdlib.h> /* Win CE puts lots of stuff here. */ +#include "prprf.h" /* for PR_snprintf */ +#else #include <time.h> #include <io.h> #include <sys/types.h> #include <sys/stat.h> +#endif #include <stdio.h> #ifndef _WIN32 @@ -46,6 +52,13 @@ #include <dos.h> #endif +#include "prio.h" + +static PRInt32 filesToRead; +static DWORD totalFileBytes; +static DWORD maxFileBytes = 250000; /* 250 thousand */ +static DWORD dwNumFiles, dwReadEvery; + static BOOL CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow) { @@ -116,7 +129,6 @@ size_t RNG_GetNoise(void *buf, size_t maxbuf) DWORD dwHigh, dwLow, dwVal; int n = 0; int nBytes; - time_t sTime; if (maxbuf <= 0) return 0; @@ -151,18 +163,81 @@ size_t RNG_GetNoise(void *buf, size_t maxbuf) if (maxbuf <= 0) return n; +#if defined(_WIN32_WCE) + { + // get the number of milliseconds elapsed since Windows CE was started. + DWORD tickCount = GetTickCount(); + nBytes = (sizeof tickCount) > maxbuf ? maxbuf : (sizeof tickCount); + memcpy(((char *)buf) + n, &tickCount, nBytes); + n += nBytes; + } +#else + { + time_t sTime; // get the time in seconds since midnight Jan 1, 1970 time(&sTime); nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime); memcpy(((char *)buf) + n, &sTime, nBytes); n += nBytes; + } +#endif return n; } +#if defined(_WIN32_WCE) static BOOL -EnumSystemFiles(void (*func)(const char *)) +EnumSystemFilesWithNSPR(const char * dirName, + BOOL recursive, + PRInt32 (*func)(const char *)) { + PRDir * pDir; + PRDirEntry * pEntry; + BOOL rv = FALSE; + + pDir = PR_OpenDir(dirName); + if (!pDir) + return rv; + while ((pEntry = PR_ReadDir(pDir, PR_SKIP_BOTH|PR_SKIP_HIDDEN)) != NULL) { + PRStatus status; + PRInt32 count; + PRInt32 stop; + PRFileInfo fileInfo; + char szFileName[_MAX_PATH]; + + count = (PRInt32)PR_snprintf(szFileName, sizeof szFileName, "%s\\%s", + dirName, PR_DirName(pEntry)); + if (count < 1) + continue; + status = PR_GetFileInfo(szFileName, &fileInfo); + if (status != PR_SUCCESS) + continue; + if (fileInfo.type == PR_FILE_FILE) { + stop = (*func)(szFileName); + rv = TRUE; + if (stop) + break; + continue; + } + if (recursive && fileInfo.type == PR_FILE_DIRECTORY) { + rv |= EnumSystemFilesWithNSPR(szFileName, recursive, func); + } + } + PR_CloseDir(pDir); + return rv; +} +#endif + +static BOOL +EnumSystemFiles(PRInt32 (*func)(const char *)) +{ +#if defined(_WIN32_WCE) + BOOL rv = FALSE; + rv |= EnumSystemFilesWithNSPR("\\Windows\\Temporary Internet Files", TRUE, func); + rv |= EnumSystemFilesWithNSPR("\\Temp", FALSE, func); + rv |= EnumSystemFilesWithNSPR("\\Windows", FALSE, func); + return rv; +#else int iStatus; char szSysDir[_MAX_PATH]; char szFileName[_MAX_PATH]; @@ -207,23 +282,31 @@ EnumSystemFiles(void (*func)(const char *)) #endif return TRUE; +#endif } -static DWORD dwNumFiles, dwReadEvery; - -static void +static PRInt32 CountFiles(const char *file) { dwNumFiles++; + return 0; } -static void +static PRInt32 ReadFiles(const char *file) { - if ((dwNumFiles % dwReadEvery) == 0) + if ((dwNumFiles % dwReadEvery) == 0) { + ++filesToRead; + } + if (filesToRead) { + DWORD prevFileBytes = totalFileBytes; RNG_FileForRNG(file); - + if (prevFileBytes < totalFileBytes) { + --filesToRead; + } + } dwNumFiles++; + return (totalFileBytes >= maxFileBytes); } static void @@ -237,6 +320,7 @@ ReadSystemFiles() RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles)); // now read 10 files + filesToRead = 10; if (dwNumFiles == 0) return; @@ -255,12 +339,14 @@ void RNG_SystemInfoForRNG(void) int nBytes; #ifdef _WIN32 MEMORYSTATUS sMem; + HANDLE hVal; +#if !defined(_WIN32_WCE) DWORD dwSerialNum; DWORD dwComponentLen; DWORD dwSysFlags; char volName[128]; DWORD dwSectors, dwBytes, dwFreeClusters, dwNumClusters; - HANDLE hVal; +#endif #else int iVal; HTASK hTask; @@ -275,10 +361,10 @@ void RNG_SystemInfoForRNG(void) sMem.dwLength = sizeof(sMem); GlobalMemoryStatus(&sMem); // assorted memory stats RNG_RandomUpdate(&sMem, sizeof(sMem)); - +#if !defined(_WIN32_WCE) dwVal = GetLogicalDrives(); RNG_RandomUpdate(&dwVal, sizeof(dwVal)); // bitfields in bits 0-25 - +#endif #else dwVal = GetFreeSpace(0); RNG_RandomUpdate(&dwVal, sizeof(dwVal)); @@ -290,10 +376,11 @@ void RNG_SystemInfoForRNG(void) #endif #ifdef _WIN32 +#if !defined(_WIN32_WCE) dwVal = sizeof(buffer); if (GetComputerName(buffer, &dwVal)) RNG_RandomUpdate(buffer, dwVal); - +#endif /* XXX This is code that got yanked because of NSPR20. We should put it * back someday. */ @@ -326,6 +413,7 @@ void RNG_SystemInfoForRNG(void) dwVal = GetCurrentProcessId(); // process ID (4 bytes) RNG_RandomUpdate(&dwVal, sizeof(dwVal)); +#if !defined(_WIN32_WCE) volName[0] = '\0'; buffer[0] = '\0'; GetVolumeInformation(NULL, @@ -349,7 +437,7 @@ void RNG_SystemInfoForRNG(void) RNG_RandomUpdate(&dwFreeClusters, sizeof(dwFreeClusters)); RNG_RandomUpdate(&dwNumClusters, sizeof(dwNumClusters)); } - +#endif #else /* is WIN16 */ hTask = GetCurrentTask(); RNG_RandomUpdate((void *)&hTask, sizeof(hTask)); @@ -372,6 +460,47 @@ void RNG_SystemInfoForRNG(void) RNG_RandomUpdate(buffer, nBytes); } +#if defined(_WIN32_WCE) +void RNG_FileForRNG(const char *filename) +{ + PRFileDesc * file; + int nBytes; + PRFileInfo infoBuf; + unsigned char buffer[1024]; + + /* windows doesn't initialize all the bytes in the stat buf, + * so initialize them all here to avoid UMRs. + */ + memset(&infoBuf, 0, sizeof infoBuf); + + if (PR_GetFileInfo(filename, &infoBuf) < 0) + return; + + RNG_RandomUpdate((unsigned char*)&infoBuf, sizeof(infoBuf)); + + file = PR_Open(filename, PR_RDONLY, 0); + if (file != NULL) { + for (;;) { + PRInt32 bytes = PR_Read(file, buffer, sizeof buffer); + + if (bytes <= 0) + break; + + RNG_RandomUpdate(buffer, bytes); + totalFileBytes += bytes; + if (totalFileBytes > maxFileBytes) + break; + } + + PR_Close(file); + } + + nBytes = RNG_GetNoise(buffer, 20); // get up to 20 bytes + RNG_RandomUpdate(buffer, nBytes); +} + +#else /* not WinCE */ + void RNG_FileForRNG(const char *filename) { FILE* file; @@ -379,7 +508,7 @@ void RNG_FileForRNG(const char *filename) struct stat stat_buf; unsigned char buffer[1024]; - static DWORD totalFileBytes = 0; + /* static DWORD totalFileBytes = 0; */ /* windows doesn't initialize all the bytes in the stat buf, * so initialize them all here to avoid UMRs. @@ -401,7 +530,7 @@ void RNG_FileForRNG(const char *filename) RNG_RandomUpdate(buffer, bytes); totalFileBytes += bytes; - if (totalFileBytes > 250000) + if (totalFileBytes > maxFileBytes) break; } @@ -412,4 +541,5 @@ void RNG_FileForRNG(const char *filename) RNG_RandomUpdate(buffer, nBytes); } +#endif /* not WinCE */ #endif /* is XP_WIN */ diff --git a/security/nss/lib/nss/Makefile b/security/nss/lib/nss/Makefile index 2eeeaef56..cb58ef545 100644 --- a/security/nss/lib/nss/Makefile +++ b/security/nss/lib/nss/Makefile @@ -42,8 +42,6 @@ include manifest.mn # (2) Include "global" configuration information. (OPTIONAL) # ####################################################################### -include $(CORE_DEPTH)/coreconf/arch.mk - include $(CORE_DEPTH)/coreconf/config.mk ####################################################################### diff --git a/security/nss/lib/nss/config.mk b/security/nss/lib/nss/config.mk index c18b1c6ae..693b6d31a 100644 --- a/security/nss/lib/nss/config.mk +++ b/security/nss/lib/nss/config.mk @@ -97,3 +97,10 @@ ifeq ($(OS_TARGET),SunOS) # dependencies (libsoftokn3.so) in the same directory where it resides. MKSHLIB += -R '$$ORIGIN' endif + +ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET))) +# Export 'mktemp' to be backward compatible with NSS 3.2.x and 3.3.x +# but do not put it in the import library. See bug 142575. +DEFINES += -DWIN32_NSS3_DLL_COMPAT +DLLFLAGS += -EXPORT:mktemp=nss_mktemp,PRIVATE +endif diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index 97bfae94f..71ec33b37 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -660,3 +660,23 @@ nss_DumpCertificateCacheInfo; ;+ local: ;+ *; ;+}; +;+NSS_3.5 { # cert creation APIs used by certutil +;+ global: +CERT_AddExtension; +CERT_CopyRDN; +CERT_CreateCertificate; +CERT_CreateValidity; +CERT_DestroyValidity; +CERT_EncodeAndAddBitStrExtension; +CERT_EncodeAuthKeyID; +CERT_EncodeBasicConstraintValue; +CERT_EncodeCRLDistributionPoints; +CERT_FinishExtensions; +CERT_StartCertExtensions; +DER_AsciiToTime; +PK11_ImportCert; +PORT_Strdup; +SECMOD_CanDeleteInternalModule; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 519f26ef8..fa4840e02 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -49,9 +49,9 @@ SEC_BEGIN_PROTOS * The format of the version string should be * "<major version>.<minor version>[.<patch level>] [<Beta>]" */ -#define NSS_VERSION "3.4 Beta" +#define NSS_VERSION "3.5 Beta" #define NSS_VMAJOR 3 -#define NSS_VMINOR 4 +#define NSS_VMINOR 5 #define NSS_VPATCH 0 #define NSS_BETA PR_TRUE @@ -132,7 +132,7 @@ SECStatus NSS_NoDB_Init(const char *configdir); /* * Close the Cert, Key databases. */ -extern void NSS_Shutdown(void); +extern SECStatus NSS_Shutdown(void); /* * set the PKCS #11 strings for the internal token. diff --git a/security/nss/lib/nss/nssinit.c b/security/nss/lib/nss/nssinit.c index 1389867fe..91a666f97 100644 --- a/security/nss/lib/nss/nssinit.c +++ b/security/nss/lib/nss/nssinit.c @@ -52,6 +52,24 @@ #include "pki3hack.h" +/* + * On Windows nss3.dll needs to export the symbol 'mktemp' to be + * fully backward compatible with the nss3.dll in NSS 3.2.x and + * 3.3.x. This symbol was unintentionally exported and its + * definition (in DBM) was moved from nss3.dll to softokn3.dll + * in NSS 3.4. See bug 142575. + */ +#ifdef WIN32_NSS3_DLL_COMPAT +#include <io.h> + +/* exported as 'mktemp' */ +char * +nss_mktemp(char *path) +{ + return _mktemp(path); +} +#endif + #define NSS_MAX_FLAG_SIZE sizeof("readOnly")+sizeof("noCertDB")+ \ sizeof("noModDB")+sizeof("forceOpen")+sizeof("passwordRequired") #define NSS_DEFAULT_MOD_NAME "NSS Internal Module" @@ -274,26 +292,76 @@ static const char *dllname = /* Should we have platform ifdefs here??? */ #define FILE_SEP '/' +static void nss_FindExternalRootPaths(const char *dbpath, const char* secmodprefix, + char** retoldpath, char** retnewpath) +{ + char *path, *oldpath = NULL, *lastsep; + int len, path_len, secmod_len, dll_len; + + path_len = PORT_Strlen(dbpath); + secmod_len = PORT_Strlen(secmodprefix); + dll_len = PORT_Strlen(dllname); + len = path_len + secmod_len + dll_len + 2; /* FILE_SEP + NULL */ + + path = PORT_Alloc(len); + if (path == NULL) return; + + /* back up to the top of the directory */ + PORT_Memcpy(path,dbpath,path_len); + if (path[path_len-1] != FILE_SEP) { + path[path_len++] = FILE_SEP; + } + PORT_Strcpy(&path[path_len],dllname); + if (secmodprefix) { + lastsep = PORT_Strrchr(secmodprefix, FILE_SEP); + if (lastsep) { + int secmoddir_len = lastsep-secmodprefix+1; /* FILE_SEP */ + oldpath = PORT_Alloc(len); + if (oldpath == NULL) { + PORT_Free(path); + return; + } + PORT_Memcpy(oldpath,path,path_len); + PORT_Memcpy(&oldpath[path_len],secmodprefix,secmoddir_len); + PORT_Strcpy(&oldpath[path_len+secmoddir_len],dllname); + } + } + *retoldpath = oldpath; + *retnewpath = path; + return; +} + +static void nss_FreeExternalRootPaths(char* oldpath, char* path) +{ + if (path) { + PORT_Free(path); + } + if (oldpath) { + PORT_Free(oldpath); + } +} + static void -nss_FindExternalRoot(const char *dbpath) +nss_FindExternalRoot(const char *dbpath, const char* secmodprefix) { - char *path; - int len, path_len; - - path_len = PORT_Strlen(dbpath); - len = path_len + PORT_Strlen(dllname) + 2; /* FILE_SEP + NULL */ - - path = PORT_Alloc(len); - if (path == NULL) return; - - /* back up to the top of the directory */ - PORT_Memcpy(path,dbpath,path_len); - if (path[path_len-1] != FILE_SEP) { - path[path_len++] = FILE_SEP; - } - PORT_Strcpy(&path[path_len],dllname); - (void) SECMOD_AddNewModule("Root Certs",path, 0, 0); - PORT_Free(path); + char *path = NULL; + char *oldpath = NULL; + PRBool hasrootcerts = PR_FALSE; + + /* + * 'oldpath' is the external root path in NSS 3.3.x or older. + * For backward compatibility we try to load the root certs + * module with the old path first. + */ + nss_FindExternalRootPaths(dbpath, secmodprefix, &oldpath, &path); + if (oldpath) { + (void) SECMOD_AddNewModule("Root Certs",oldpath, 0, 0); + hasrootcerts = SECMOD_HasRootCerts(); + } + if (path && !hasrootcerts) { + (void) SECMOD_AddNewModule("Root Certs",path, 0, 0); + } + nss_FreeExternalRootPaths(oldpath, path); return; } #endif @@ -390,7 +458,7 @@ loser: /* only servers need this. We currently do not have a mac server */ if ((!noModDB) && (!noCertDB) && (!noRootInit)) { if (!SECMOD_HasRootCerts()) { - nss_FindExternalRoot(configdir); + nss_FindExternalRoot(configdir, secmodName); } } #endif @@ -454,13 +522,16 @@ NSS_NoDB_Init(const char * configdir) PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE); } -void +SECStatus NSS_Shutdown(void) { + SECStatus rv; + SECOID_Shutdown(); - SECMOD_Shutdown(); STAN_Shutdown(); + rv = SECMOD_Shutdown(); nss_IsInitted = PR_FALSE; + return rv; } diff --git a/security/nss/lib/pk11wrap/dev3hack.c b/security/nss/lib/pk11wrap/dev3hack.c index 43a12628b..9ffd63fc9 100644 --- a/security/nss/lib/pk11wrap/dev3hack.c +++ b/security/nss/lib/pk11wrap/dev3hack.c @@ -43,12 +43,13 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "pkit.h" #endif /* PKIT_H */ -#ifndef DEVT_H -#include "devt.h" -#endif /* DEVT_H */ +#ifndef DEVM_H +#include "devm.h" +#endif /* DEVM_H */ #include "pki3hack.h" #include "dev3hack.h" +#include "pkim.h" #ifndef BASE_H #include "base.h" @@ -117,17 +118,24 @@ static NSSSlot * nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSSlot *rvSlot; - rvSlot = nss_ZNEW(td->arena, NSSSlot); + NSSArena *arena; + arena = nssArena_Create(); + if (!arena) { + return NULL; + } + rvSlot = nss_ZNEW(arena, NSSSlot); if (!rvSlot) { + nssArena_Destroy(arena); return NULL; } - rvSlot->refCount = 1; + rvSlot->base.refCount = 1; + rvSlot->base.lock = PZ_NewLock(nssILockOther); + rvSlot->base.arena = arena; rvSlot->pk11slot = nss3slot; rvSlot->epv = nss3slot->functionList; rvSlot->slotID = nss3slot->slotID; - rvSlot->trustDomain = td; /* Grab the slot name from the PKCS#11 fixed-length buffer */ - rvSlot->name = nssUTF8_Duplicate(nss3slot->slot_name,td->arena); + rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name,td->arena); return rvSlot; } @@ -135,24 +143,40 @@ NSS_IMPLEMENT NSSToken * nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSToken *rvToken; - rvToken = nss_ZNEW(td->arena, NSSToken); + NSSArena *arena; + arena = nssArena_Create(); + if (!arena) { + return NULL; + } + rvToken = nss_ZNEW(arena, NSSToken); if (!rvToken) { + nssArena_Destroy(arena); return NULL; } - rvToken->refCount = 1; + rvToken->base.refCount = 1; + rvToken->base.lock = PZ_NewLock(nssILockOther); + rvToken->base.arena = arena; rvToken->pk11slot = nss3slot; rvToken->epv = nss3slot->functionList; rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); + /* The above test was used in 3.4, for this cache have it always on */ + if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) { + rvToken->cache = nssTokenObjectCache_Create(rvToken, + PR_TRUE, PR_TRUE, PR_TRUE); + if (!rvToken->cache) { + nssArena_Destroy(arena); + return (NSSToken *)NULL; + } + } rvToken->trustDomain = td; /* Grab the token name from the PKCS#11 fixed-length buffer */ - rvToken->name = nssUTF8_Duplicate(nss3slot->token_name,td->arena); + rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name,td->arena); rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot); rvToken->slot->token = rvToken; rvToken->defaultSession->slot = rvToken->slot; - rvToken->arena = td->arena; return rvToken; } @@ -162,7 +186,7 @@ nssToken_UpdateName(NSSToken *token) if (!token) { return; } - token->name = nssUTF8_Duplicate(token->pk11slot->token_name,token->arena); + token->base.name = nssUTF8_Duplicate(token->pk11slot->token_name,token->base.arena); } NSS_IMPLEMENT PRBool @@ -174,6 +198,15 @@ nssSlot_IsPermanent return slot->pk11slot->isPerm; } +NSS_IMPLEMENT PRBool +nssSlot_IsFriendly +( + NSSSlot *slot +) +{ + return PK11_IsFriendly(slot->pk11slot); +} + NSS_IMPLEMENT PRStatus nssToken_Refresh(NSSToken *token) { @@ -183,12 +216,11 @@ nssToken_Refresh(NSSToken *token) return PR_SUCCESS; } nss3slot = token->pk11slot; - token->defaultSession = nssSession_ImportNSS3Session(token->slot->arena, + token->defaultSession = nssSession_ImportNSS3Session(token->slot->base.arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); - nssToken_DestroyCertList(token, PR_TRUE); - return nssToken_LoadCerts(token); + return PR_SUCCESS; } NSS_IMPLEMENT PRStatus @@ -198,12 +230,44 @@ nssSlot_Refresh ) { PK11SlotInfo *nss3slot = slot->pk11slot; + PRBool doit = PR_FALSE; + if (slot->token->base.name[0] == 0) { + doit = PR_TRUE; + } if (PK11_InitToken(nss3slot, PR_FALSE) != SECSuccess) { return PR_FAILURE; } + if (doit) { + nssTrustDomain_UpdateCachedTokenCerts(slot->token->trustDomain, + slot->token); + } return nssToken_Refresh(slot->token); } +NSS_IMPLEMENT PRStatus +nssToken_GetTrustOrder +( + NSSToken *tok +) +{ + PK11SlotInfo *slot; + SECMODModule *module; + slot = tok->pk11slot; + module = PK11_GetModule(slot); + return module->trustOrder; +} + +NSS_IMPLEMENT PRBool +nssSlot_IsLoggedIn +( + NSSSlot *slot +) +{ + if (!slot->pk11slot->needLogin) { + return PR_TRUE; + } + return PK11_IsLoggedIn(slot->pk11slot, NULL); +} NSSTrustDomain * @@ -212,25 +276,19 @@ nssToken_GetTrustDomain(NSSToken *token) return token->trustDomain; } -typedef enum { - nssPK11Event_DefaultSessionRO = 0, - nssPK11Event_DefaultSessionRW = 1 -} nssPK11Event; +NSS_EXTERN PRStatus +nssTrustDomain_RemoveTokenCertsFromCache +( + NSSTrustDomain *td, + NSSToken *token +); NSS_IMPLEMENT PRStatus -nssToken_Nofify +nssToken_NofifyCertsNotVisible ( - NSSToken *tok, - nssPK11Event event + NSSToken *tok ) - { -#ifdef notdef - switch (event) { - default: - return PR_FAILURE; - } -#endif - return PR_FAILURE; + return nssTrustDomain_RemoveTokenCertsFromCache(tok->trustDomain, tok); } diff --git a/security/nss/lib/pk11wrap/dev3hack.h b/security/nss/lib/pk11wrap/dev3hack.h index 19f9bbb8b..d2e3ab4e1 100644 --- a/security/nss/lib/pk11wrap/dev3hack.h +++ b/security/nss/lib/pk11wrap/dev3hack.h @@ -58,12 +58,6 @@ void PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst); NSSToken * PK11Slot_GetNSSToken(PK11SlotInfo *sl); -NSS_EXTERN PRStatus -nssToken_LoadCerts(NSSToken *token); - -NSS_EXTERN void -nssToken_UpdateTrustForCerts(NSSToken *token); - PR_END_EXTERN_C #endif /* DEVNSS3HACK_H */ diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index 9611ff06f..ae0629d49 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -58,11 +58,12 @@ #include "pki3hack.h" #include "dev3hack.h" -#include "dev.h" +#include "devm.h" #include "nsspki.h" #include "pki.h" #include "pkim.h" #include "pkitm.h" +#include "pkistore.h" /* to remove temp cert */ #define PK11_SEARCH_CHUNKSIZE 10 @@ -89,50 +90,6 @@ static PRStatus convert_cert(NSSCertificate *c, void *arg) return (secrv) ? PR_FAILURE : PR_SUCCESS; } -static PRStatus convert_and_cache_cert(NSSCertificate *c, void *arg) -{ - PRStatus nssrv; - NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - struct nss3_cert_cbstr *nss3cb = (struct nss3_cert_cbstr *)arg; - NSSCertificate *cp = nssCertificate_AddRef(c); - /* The cert coming in has been retrieved from a token. It was not in - * the cache when the search was begun. But it may be in the cache now, - * and if it isn't, it will be, because it is going to be cracked into - * a CERTCertificate and fed into the callback. - */ - nssrv = nssTrustDomain_AddCertsToCache(td, &c, 1); - /* This is why the hack of copying the cert was done above. The pointer - * c passed to this function is provided by retrieve_cert. That function - * will destroy the pointer once this function returns. Since c is a local - * copy, there is no way to notify retrieve_cert if it has changed. That - * would happen if the above call to add it to the cache found the cert - * already there. In that case, the pointer c passed to the callback - * below will be the cached cert, and the pointer c that retrieve_cert - * has will be the same as the copy made above. Thus, retrieve_cert will - * destroy the reference to the copy, the callback will use the reference - * to the cached entry, and everyone should be happy. - */ - nssrv = convert_cert(c, arg); - /* This function owns a reference to the cert, either from the AddRef - * or by getting it from the cache. - */ - CERT_DestroyCertificate(STAN_GetCERTCertificate(c)); - return nssrv; -} - -/* this is redeclared from trustdomain.c, but this code is just 3.4 glue - * anyway - */ -static void cert_destructor(void *el) -{ - NSSCertificate *c = (NSSCertificate *)el; - CERTCertificate *cert = STAN_GetCERTCertificate(c); - /* It's already been obtained as a CERTCertificate, so it must - * be destroyed as one - */ - CERT_DestroyCertificate(cert); -} - void PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst) { @@ -435,59 +392,54 @@ pk11_isID0(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID) return isZero; } - + +/* + * Create an NSSCertificate from a slot/certID pair, return it as a + * CERTCertificate. + */ CERTCertificate *pk11_fastCert(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, CK_ATTRIBUTE *privateLabel, char **nickptr) { - CK_ATTRIBUTE certTemp[] = { - { CKA_ID, NULL, 0 }, - { CKA_VALUE, NULL, 0 }, - { CKA_LABEL, NULL, 0 } - }; - CK_ATTRIBUTE *id = &certTemp[0]; - CK_ATTRIBUTE *certDER = &certTemp[1]; - CK_ATTRIBUTE *label = &certTemp[2]; - SECItem derCert; - int csize = sizeof(certTemp)/sizeof(certTemp[0]); - PRArenaPool *arena; - char *nickname; - CERTCertificate *cert; - CK_RV crv; + NSSCertificate *c; + nssCryptokiObject *co; + nssPKIObject *pkio; + NSSToken *token; + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) return NULL; - /* - * grab the der encoding - */ - crv = PK11_GetAttributes(arena,slot,certID,certTemp,csize); - if (crv != CKR_OK) { - PORT_FreeArena(arena,PR_FALSE); - PORT_SetError( PK11_MapError(crv) ); + /* Get the cryptoki object from the handle */ + token = PK11Slot_GetNSSToken(slot); + co = nssCryptokiObject_Create(token, token->defaultSession, certID); + if (!co) { return NULL; } - /* - * build a certificate out of it - */ - derCert.data = (unsigned char*)certDER->pValue; - derCert.len = certDER->ulValueLen; + /* Create a PKI object from the cryptoki instance */ + pkio = nssPKIObject_Create(NULL, co, td, NULL); + if (!pkio) { + nssCryptokiObject_Destroy(co); + return NULL; + } - /* figure out the nickname.... */ - nickname = pk11_buildNickname(slot,label,privateLabel,id); - cert = CERT_DecodeDERCertificate(&derCert, PR_TRUE, nickname); - if (cert) { - cert->dbhandle = (CERTCertDBHandle *) - nssToken_GetTrustDomain(slot->nssToken); + /* Create a certificate */ + c = nssCertificate_Create(pkio); + if (!c) { + nssPKIObject_Destroy(pkio); + return NULL; } - + + /* Build the old-fashioned nickname */ if (nickptr) { - *nickptr = nickname; - } else { - if (nickname) PORT_Free(nickname); + CK_ATTRIBUTE label, id; + label.type = CKA_LABEL; + label.pValue = co->label; + label.ulValueLen = PORT_Strlen(co->label); + id.type = CKA_ID; + id.pValue = c->id.data; + id.ulValueLen = c->id.size; + *nickptr = pk11_buildNickname(slot, &label, privateLabel, &id); } - PORT_FreeArena(arena,PR_FALSE); - return cert; + return STAN_GetCERTCertificate(c); } CK_TRUST @@ -1015,7 +967,9 @@ pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), rv = PK11_Authenticate(le->slot, PR_FALSE, wincx); if (rv != SECSuccess) continue; } - (*callback)(le->slot,arg); + if (callback) { + (*callback)(le->slot,arg); + } } PK11_FreeSlotList(list); @@ -1063,6 +1017,10 @@ PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); struct fake_der_cb_argstr fda; struct nss3_cert_cbstr pk11cb; + + /* authenticate to the tokens first */ + (void) pk11_TraverseAllSlots( NULL, NULL, wincx); + fda.callback = callback; fda.arg = arg; pk11cb.callback = fake_der_cb; @@ -1215,123 +1173,37 @@ PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, return objID; } -static PRStatus -get_newest_cert(NSSCertificate *c, void *arg) -{ - nssDecodedCert *dc, *founddc; - NSSCertificate **cfound = (NSSCertificate **)arg; - if (!*cfound) { - *cfound = nssCertificate_AddRef(c); - return PR_SUCCESS; - } - dc = nssCertificate_GetDecoding(c); - founddc = nssCertificate_GetDecoding(*cfound); - if (!founddc->isNewerThan(founddc, dc)) { - CERT_DestroyCertificate(STAN_GetCERTCertificate(*cfound)); - *cfound = nssCertificate_AddRef(c); - } - return PR_SUCCESS; -} - -struct token_cbstr { - NSSToken *token; - PRStatus (* callback)(NSSCertificate *c, void *arg); - void *cbarg; -}; - -/* This callback matches all certs on a given token. It is used to filter - * cert lists to only those certs on a particular token. - */ -static PRStatus -token_callback(NSSCertificate *c, void *arg) -{ - nssListIterator *instances; - nssCryptokiInstance *instance; - PRBool isToken = PR_FALSE; - struct token_cbstr *token_cb = (struct token_cbstr *)arg; - instances = c->object.instances; - for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); - instance != (nssCryptokiInstance *)NULL; - instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { - if (instance->token == token_cb->token) { - isToken = PR_TRUE; - break; - } - } - nssListIterator_Finish(instances); - if (isToken) { - return (*token_cb->callback)(c, token_cb->cbarg); - } else { - return PR_SUCCESS; - } -} - -/* match all token certs with a nickname */ -static nssList * -filter_token_certs_nickname(NSSToken *token, NSSUTF8 *nickname) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRStatus nssrv; - nssList *rvList; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvList = nssList_Create(NULL, PR_FALSE); - if (!rvList) { - nssListIterator_Destroy(certs); - return NULL; - } - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - NSSUTF8 *tokenNick = NSSCertificate_GetNickname(cert, token); - if (!tokenNick) continue; - if (nssUTF8_Equal(tokenNick, nickname, &nssrv)) { - nssList_Add(rvList, nssCertificate_AddRef(cert)); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - if (nssList_Count(rvList) == 0) { - nssList_Destroy(rvList); - rvList = NULL; - } - return rvList; -} - -/* match all token certs with an email address */ -static nssList * -filter_token_certs_email(NSSToken *token, NSSASCII7 *email) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRStatus nssrv; - nssList *rvList; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvList = nssList_Create(NULL, PR_FALSE); - if (!rvList) { - nssListIterator_Destroy(certs); - return NULL; - } - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - if (!cert->email) continue; - if (nssUTF8_Equal(cert->email, email, &nssrv)) { - nssList_Add(rvList, nssCertificate_AddRef(cert)); +static void +transfer_token_certs_to_collection(nssList *certList, NSSToken *token, + nssPKIObjectCollection *collection) +{ + NSSCertificate **certs; + PRUint32 i, count; + NSSToken **tokens, **tp; + count = nssList_Count(certList); + if (count == 0) { + return; + } + certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count); + if (!certs) { + return; + } + nssList_GetArray(certList, (void **)certs, count); + for (i=0; i<count; i++) { + tokens = nssPKIObject_GetTokens(&certs[i]->object, NULL); + if (tokens) { + for (tp = tokens; *tp; tp++) { + if (*tp == token) { + nssPKIObjectCollection_AddObject(collection, + (nssPKIObject *)certs[i]); + } + } + nssTokenArray_Destroy(tokens); } + /* *must* be a valid CERTCertificate, came from cache */ + CERT_DestroyCertificate(STAN_GetCERTCertificate(certs[i])); } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - if (nssList_Count(rvList) == 0) { - nssList_Destroy(rvList); - rvList = NULL; - } - return rvList; + nss_ZFreeIf(certs); } CERTCertificate * @@ -1349,8 +1221,10 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { PORT_Free(certID); return cert; #else + PRStatus status; CERTCertificate *rvCert = NULL; NSSCertificate *cert = NULL; + NSSCertificate **certs = NULL; NSSUsage usage; NSSToken *token; PK11SlotInfo *slot = NULL; @@ -1375,111 +1249,79 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { token = PK11Slot_GetNSSToken(slot); } if (token) { - nssTokenCertSearch search; - struct token_cbstr token_cb; nssList *certList; - + nssCryptokiObject **instances; + nssPKIObjectCollection *collection; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; if (!PK11_IsPresent(slot)) { - return NULL; + goto loser; } if (!PK11_IsFriendly(slot)) { if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) { - PK11_FreeSlot(slot); - return NULL; + goto loser; } } - /* find best cert on token */ - if (!nssToken_SearchCerts(token, NULL)) { - /* token certs are in cache, filter the list of token certs to - * match the nickname - */ - certList = filter_token_certs_nickname(token, nickname); - if (certList) { - nssCertificateList_DoCallback(certList, - get_newest_cert, - (void *)&cert); - } - } else { - /* find matching certs on the token */ - certList = nssList_Create(NULL, PR_FALSE); - if (!certList) return NULL; - /* first, get all matching certs from the cache */ - (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, - nickname, - certList); - /* set the search criteria */ - token_cb.callback = get_newest_cert; - token_cb.cbarg = (void *)&cert; - token_cb.token = token; - search.callback = token_callback; - search.cbarg = &token_cb; - search.cached = certList; - search.searchType = nssTokenSearchType_TokenOnly; - /* now search the token */ - nssToken_TraverseCertificatesByNickname(token, NULL, - (NSSUTF8 *)nickname, - &search); - /* filter the list of cached certs for only those on the token */ - nssCertificateList_DoCallback(certList, - token_callback, - &token_cb); - } - if (certList) { - nssList_Clear(certList, cert_destructor); - nssList_Destroy(certList); + collection = nssCertificateCollection_Create(defaultTD, NULL); + if (!collection) { + goto loser; } + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) { + nssPKIObjectCollection_Destroy(collection); + goto loser; + } + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, + nickname, + certList); + transfer_token_certs_to_collection(certList, token, collection); + instances = nssToken_FindCertificatesByNickname(token, + NULL, + nickname, + tokenOnly, + 0, + &status); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); /* if it wasn't found, repeat the process for email address */ - if (!cert) { - if (!nssToken_SearchCerts(token, NULL)) { - certList = filter_token_certs_email(token, nickname); - if (certList) { - nssCertificateList_DoCallback(certList, - get_newest_cert, - (void *)&cert); - } - } else { - certList = nssList_Create(NULL, PR_FALSE); - if (!certList) return NULL; - (void)nssTrustDomain_GetCertsForEmailAddressFromCache( - defaultTD, + if (nssPKIObjectCollection_Count(collection) == 0 && + PORT_Strchr(nickname, '@') != NULL) + { + (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, nickname, certList); - search.cached = certList; - nssToken_TraverseCertificatesByEmail(token, NULL, - (NSSASCII7 *)nickname, - &search); - nssCertificateList_DoCallback(certList, - token_callback, - &token_cb); - } - if (certList) { - nssList_Clear(certList, cert_destructor); - nssList_Destroy(certList); - } - } - if (cert) { - (void)nssTrustDomain_AddCertsToCache(defaultTD, &cert, 1); + transfer_token_certs_to_collection(certList, token, collection); + instances = nssToken_FindCertificatesByEmail(token, + NULL, + nickname, + tokenOnly, + 0, + &status); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + } + certs = nssPKIObjectCollection_GetCertificates(collection, + NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + if (certs) { + cert = nssCertificateArray_FindBestCertificate(certs, NULL, + &usage, NULL); rvCert = STAN_GetCERTCertificate(cert); + nssCertificateArray_Destroy(certs); } + nssList_Destroy(certList); } if (slot) { PK11_FreeSlot(slot); } if (nickCopy) PORT_Free(nickCopy); return rvCert; -#endif -} - -static PRStatus -collect_certs(NSSCertificate *c, void *arg) -{ - nssList *list = (nssList *)arg; - /* Add the cert to the return list if not present */ - if (!nssList_Get(list, (void *)c)) { - nssCertificate_AddRef(c); - nssList_Add(list, (void *)c); +loser: + if (slot) { + PK11_FreeSlot(slot); } - return PR_SUCCESS; + if (nickCopy) PORT_Free(nickCopy); + return NULL; +#endif } CERTCertList * @@ -1509,12 +1351,12 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { PORT_Free(certID); return certList; #else - PRStatus nssrv; char *nickCopy; char *delimit = NULL; char *tokenName; int i; CERTCertList *certList = NULL; + nssPKIObjectCollection *collection = NULL; NSSCertificate **foundCerts = NULL; NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); NSSCertificate *c; @@ -1538,37 +1380,45 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { token = PK11Slot_GetNSSToken(slot); } if (token) { - nssTokenCertSearch search; - PRUint32 count; + PRStatus status; nssList *nameList; + nssCryptokiObject **instances; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; if (!PK11_IsFriendly(slot)) { if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) { PK11_FreeSlot(slot); + if (nickCopy) PORT_Free(nickCopy); return NULL; } } - if (!nssToken_SearchCerts(token, NULL)) { - nameList = filter_token_certs_nickname(token, nickname); - } else { - nameList = nssList_Create(NULL, PR_FALSE); - if (!nameList) return NULL; - (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, - nickname, - nameList); - /* set the search criteria */ - search.callback = collect_certs; - search.cbarg = nameList; - search.cached = nameList; - search.searchType = nssTokenSearchType_TokenOnly; - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - nickname, &search); - } - if (nameList) { - count = nssList_Count(nameList); - foundCerts = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); - nssList_GetArray(nameList, (void **)foundCerts, count); - nssList_Destroy(nameList); + collection = nssCertificateCollection_Create(defaultTD, NULL); + if (!collection) { + PK11_FreeSlot(slot); + if (nickCopy) PORT_Free(nickCopy); + return NULL; + } + nameList = nssList_Create(NULL, PR_FALSE); + if (!nameList) { + PK11_FreeSlot(slot); + if (nickCopy) PORT_Free(nickCopy); + return NULL; } + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, + nickname, + nameList); + transfer_token_certs_to_collection(nameList, token, collection); + instances = nssToken_FindCertificatesByNickname(token, + NULL, + nickname, + tokenOnly, + 0, + &status); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + nssList_Destroy(nameList); + foundCerts = nssPKIObjectCollection_GetCertificates(collection, + NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); } if (slot) { PK11_FreeSlot(slot); @@ -1577,7 +1427,10 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { if (foundCerts) { certList = CERT_NewCertList(); for (i=0, c = *foundCerts; c; c = foundCerts[++i]) { - CERT_AddCertToListTail(certList, STAN_GetCERTCertificate(c)); + CERTCertificate *certCert = STAN_GetCERTCertificate(c); + if (certCert) { + CERT_AddCertToListTail(certList, certCert); + } } if (CERT_LIST_HEAD(certList) == NULL) { CERT_DestroyCertList(certList); @@ -1692,6 +1545,7 @@ PK11_MakeIDFromPubKey(SECItem *pubKeyData) { SECStatus PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) { +#ifdef NSS_CLASSIC int len = 0; SECItem *keyID = pk11_mkcertKeyID(cert); CK_ATTRIBUTE keyAttrs[] = { @@ -1715,6 +1569,7 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, { CKA_SERIAL_NUMBER, NULL, 0}, { CKA_VALUE, NULL, 0}, { CKA_NETSCAPE_TRUST, NULL, 0}, + { CKA_NETSCAPE_EMAIL, NULL, 0}, }; int certCount = sizeof(certAttrs)/sizeof(certAttrs[0]), keyCount = 2; int realCount = 0; @@ -1765,6 +1620,11 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, PK11_SETATTRS(attrs,CKA_NETSCAPE_TRUST, certUsage, sizeof(SECCertUsage)); attrs++; + if (cert->emailAddr) { + PK11_SETATTRS(attrs,CKA_NETSCAPE_EMAIL, cert->emailAddr, + PORT_Strlen(cert->emailAddr); + attrs++; + } } realCount = attrs - certAttrs; PORT_Assert(realCount <= certCount); @@ -1815,24 +1675,13 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, instance->token = slot->nssToken; instance->handle = cert->pkcs11ID; instance->isTokenObject = PR_TRUE; - nssList_Add(c->object.instanceList, instance); - /* XXX Fix this! */ - nssListIterator_Destroy(c->object.instances); - c->object.instances = nssList_CreateIterator(c->object.instanceList); + nssPKIObject_AddInstance(&c->object, instance); } else { cert->nssCertificate = STAN_GetNSSCertificate(cert); } } cert->trust = nssTrust_GetCERTCertTrustForCert(cert->nssCertificate, cert); token = PK11Slot_GetNSSToken(slot); - if (token->certList) { - /* create a persistent reference for the token */ - NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - nssCertificate_AddRef(cert->nssCertificate); - nssList_Add(token->certList, cert->nssCertificate); - /* and add the cert to the cache */ - nssTrustDomain_AddCertsToCache(td, &cert->nssCertificate, 1); - } done: if (derSerial.data) PORT_Free(derSerial.data); @@ -1842,7 +1691,89 @@ done: PORT_Free(certUsage); } return rv; +#else + PRStatus status; + NSSCertificate *c; + nssCryptokiObject *keyobj, *certobj; + NSSToken *token = PK11Slot_GetNSSToken(slot); + SECItem *keyID = pk11_mkcertKeyID(cert); + char *emailAddr = NULL; + + if (keyID == NULL) { + goto loser; + } + + if (PK11_IsInternal(slot) && cert->emailAddr) { + emailAddr = cert->emailAddr; + } + + /* need to get the cert as a stan cert */ + if (cert->nssCertificate) { + c = cert->nssCertificate; + } else { + c = STAN_GetNSSCertificate(cert); + } + + if (c->object.cryptoContext) { + /* Delete the temp instance */ + nssCertificateStore_Remove(c->object.cryptoContext->certStore, c); + c->object.cryptoContext = NULL; + cert->istemp = PR_FALSE; + cert->isperm = PR_TRUE; + } + + /* set the id for the cert */ + nssItem_Create(c->object.arena, &c->id, keyID->len, keyID->data); + if (!c->id.data) { + goto loser; + } + + if (key != CK_INVALID_HANDLE) { + /* create an object for the key, ... */ + keyobj = nss_ZNEW(NULL, nssCryptokiObject); + if (!keyobj) { + goto loser; + } + keyobj->token = nssToken_AddRef(token); + keyobj->handle = key; + keyobj->isTokenObject = PR_TRUE; + /* ... in order to set matching attributes for the key */ + status = nssCryptokiPrivateKey_SetCertificate(keyobj, NULL, nickname, + &c->id, &c->subject); + nssCryptokiObject_Destroy(keyobj); + if (status != PR_SUCCESS) { + goto loser; + } + } + + /* do the token import */ + certobj = nssToken_ImportCertificate(token, NULL, + NSSCertificateType_PKIX, + &c->id, + nickname, + &c->encoding, + &c->issuer, + &c->subject, + &c->serial, + emailAddr, + PR_TRUE); + if (!certobj) { + goto loser; + } + /* add the new instance to the cert, force an update of the + * CERTCertificate, and finish + */ + nssPKIObject_AddInstance(&c->object, certobj); + nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); + (void)STAN_ForceCERTCertificateUpdate(c); + SECITEM_FreeItem(keyID,PR_TRUE); + return SECSuccess; +loser: + SECITEM_FreeItem(keyID,PR_TRUE); + PORT_SetError(SEC_ERROR_ADDING_CERT); + return SECFailure; +#endif } /* @@ -1977,6 +1908,9 @@ PK11_KeyForDERCertExists(SECItem *derCert, CK_OBJECT_HANDLE *keyPtr, CERTCertificate *cert; PK11SlotInfo *slot = NULL; + /* letting this use go -- the only thing that the cert is used for is + * to get the ID attribute. + */ cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return NULL; @@ -2009,7 +1943,8 @@ PK11_ImportDERCertForKey(SECItem *derCert, char *nickname,void *wincx) { CERTCertificate *cert; PK11SlotInfo *slot = NULL; - cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); + cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + derCert, NULL, PR_FALSE, PR_FALSE); if (cert == NULL) return NULL; slot = PK11_ImportCertForKey(cert, nickname, wincx); @@ -2434,12 +2369,18 @@ PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, SECITEM_FreeItem(derSerial, PR_TRUE); return STAN_GetCERTCertificate(cert); } +retry: cert = NSSTrustDomain_FindCertificateByIssuerAndSerialNumber( STAN_GetDefaultTrustDomain(), &issuer, &serial); if (cert) { rvCert = STAN_GetCERTCertificate(cert); + /* Check to see if the cert's token is still there */ + if (!PK11_IsPresent(rvCert->slot)) { + CERT_DestroyCertificate(rvCert); + goto retry; + } if (slotPtr) *slotPtr = PK11_ReferenceSlot(rvCert->slot); } SECITEM_FreeItem(derSerial, PR_TRUE); @@ -2597,72 +2538,6 @@ PK11_TraverseCertsForSubject(CERTCertificate *cert, return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg); } -/* Find all certs with a given subject in the list of token certs */ -static nssList * -filter_token_certs_subject(NSSToken *token, NSSDER *subject) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRStatus nssrv; - nssList *rvList; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvList = nssList_Create(NULL, PR_FALSE); - if (!rvList) { - nssListIterator_Destroy(certs); - return NULL; - } - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - if (nssItem_Equal(&cert->subject, subject, &nssrv)) { - nssList_Add(rvList, nssCertificate_AddRef(cert)); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - if (nssList_Count(rvList) == 0) { - nssList_Destroy(rvList); - rvList = NULL; - } - return rvList; -} - -/* remove all certs in a list that are not on the given token */ -static void -filter_list_for_token_certs(nssList *certList, NSSToken *token) -{ - nssListIterator *instances, *certs; - nssCryptokiInstance *instance; - NSSCertificate *c; - PRBool isToken = PR_FALSE; - certs = nssList_CreateIterator(certList); - if (!certs) return; - for (c = (NSSCertificate *)nssListIterator_Start(certs); - c != (NSSCertificate *)NULL; - c = (NSSCertificate *)nssListIterator_Next(certs)) { - instances = c->object.instances; - for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); - instance != (nssCryptokiInstance *)NULL; - instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { - if (instance->token == token) { - isToken = PR_TRUE; - break; - } - } - nssListIterator_Finish(instances); - if (!isToken) { - /* safe since iterator is copied */ - nssList_Remove(certList, c); - CERT_DestroyCertificate(STAN_GetCERTCertificate(c)); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); -} - SECStatus PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, SECStatus(* callback)(CERTCertificate*, void *), void *arg) @@ -2695,48 +2570,53 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, return PK11_TraverseSlot(slot, &callarg); #else - struct nss3_cert_cbstr pk11cb; PRStatus nssrv = PR_SUCCESS; NSSToken *token; NSSDER subject; NSSTrustDomain *td; nssList *subjectList; - nssTokenCertSearch search; - pk11cb.callback = callback; - pk11cb.arg = arg; + nssPKIObjectCollection *collection; + nssCryptokiObject **instances; + NSSCertificate **certs; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; td = STAN_GetDefaultTrustDomain(); NSSITEM_FROM_SECITEM(&subject, &cert->derSubject); token = PK11Slot_GetNSSToken(slot); - if (!nssToken_SearchCerts(token, NULL)) { - subjectList = filter_token_certs_subject(token, &subject); - if (subjectList) { - nssrv = nssCertificateList_DoCallback(subjectList, - convert_cert, &pk11cb); + if (!nssToken_IsPresent(token)) { + return SECSuccess; + } + collection = nssCertificateCollection_Create(td, NULL); + if (!collection) { + return SECFailure; + } + subjectList = nssList_Create(NULL, PR_FALSE); + if (!subjectList) { + nssPKIObjectCollection_Destroy(collection); + return SECFailure; + } + (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, + subjectList); + transfer_token_certs_to_collection(subjectList, token, collection); + instances = nssToken_FindCertificatesBySubject(token, NULL, + &subject, + tokenOnly, 0, &nssrv); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + nssList_Destroy(subjectList); + certs = nssPKIObjectCollection_GetCertificates(collection, + NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + if (certs) { + CERTCertificate *oldie; + NSSCertificate **cp; + for (cp = certs; *cp; cp++) { + oldie = STAN_GetCERTCertificate(*cp); + if ((*callback)(oldie, arg) != SECSuccess) { + nssrv = PR_FAILURE; + break; + } } - } else { - subjectList = nssList_Create(NULL, PR_FALSE); - if (!subjectList) { - return SECFailure; - } - (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, - subjectList); - /* set the search criteria */ - search.callback = convert_and_cache_cert; - search.cbarg = &pk11cb; - search.cached = subjectList; - search.searchType = nssTokenSearchType_TokenOnly; - pk11cb.cached = subjectList; - nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, - &subject, &search); - if (nssrv == PR_SUCCESS) { - filter_list_for_token_certs(subjectList, token); - nssrv = nssCertificateList_DoCallback(subjectList, - convert_cert, &pk11cb); - } - } - if (subjectList) { - nssList_Clear(subjectList, cert_destructor); - nssList_Destroy(subjectList); + nssCertificateArray_Destroy(certs); } return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; #endif @@ -2785,10 +2665,17 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, NSSTrustDomain *td; NSSUTF8 *nick; PRBool created = PR_FALSE; - nssTokenCertSearch search; - nssList *nameList; + nssCryptokiObject **instances; + nssPKIObjectCollection *collection = NULL; + NSSCertificate **certs; + nssList *nameList = NULL; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; pk11cb.callback = callback; pk11cb.arg = arg; + token = PK11Slot_GetNSSToken(slot); + if (!nssToken_IsPresent(token)) { + return SECSuccess; + } if (nickname->data[nickname->len-1] != '\0') { nick = nssUTF8_Create(NULL, nssStringType_UTF8String, nickname->data, nickname->len); @@ -2797,36 +2684,50 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, nick = (NSSUTF8 *)nickname->data; } td = STAN_GetDefaultTrustDomain(); - token = PK11Slot_GetNSSToken(slot); - if (!nssToken_SearchCerts(token, NULL)) { - nameList = filter_token_certs_nickname(token, nick); - if (nameList) { - nssrv = nssCertificateList_DoCallback(nameList, - convert_cert, &pk11cb); - } - } else { - nameList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList); - /* set the search criteria */ - search.callback = convert_and_cache_cert; - search.cbarg = &pk11cb; - search.cached = nameList; - search.searchType = nssTokenSearchType_TokenOnly; - pk11cb.cached = nameList; - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - nick, &search); - if (nssrv == PR_SUCCESS) { - filter_list_for_token_certs(nameList, token); - nssrv = nssCertificateList_DoCallback(nameList, - convert_cert, &pk11cb); + collection = nssCertificateCollection_Create(td, NULL); + if (!collection) { + goto loser; + } + nameList = nssList_Create(NULL, PR_FALSE); + if (!nameList) { + goto loser; + } + (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList); + transfer_token_certs_to_collection(nameList, token, collection); + instances = nssToken_FindCertificatesByNickname(token, NULL, + nick, + tokenOnly, 0, &nssrv); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + nssList_Destroy(nameList); + certs = nssPKIObjectCollection_GetCertificates(collection, + NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + if (certs) { + CERTCertificate *oldie; + NSSCertificate **cp; + for (cp = certs; *cp; cp++) { + oldie = STAN_GetCERTCertificate(*cp); + if ((*callback)(oldie, arg) != SECSuccess) { + nssrv = PR_FAILURE; + break; + } } + nssCertificateArray_Destroy(certs); + } + if (created) nss_ZFreeIf(nick); + return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; +loser: + if (created) { + nss_ZFreeIf(nick); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); } if (nameList) { - nssList_Clear(nameList, cert_destructor); nssList_Destroy(nameList); } - if (created) nss_ZFreeIf(nick); - return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; + return SECFailure; #endif } @@ -2862,62 +2763,49 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot, #else PRStatus nssrv; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - struct nss3_cert_cbstr pk11cb; NSSToken *tok; nssList *certList = NULL; - nssTokenCertSearch search; - pk11cb.callback = callback; - pk11cb.arg = arg; + nssCryptokiObject **instances; + nssPKIObjectCollection *collection; + NSSCertificate **certs; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; tok = PK11Slot_GetNSSToken(slot); - if (!nssToken_SearchCerts(tok, NULL)) { - certList = tok->certList; - nssrv = nssCertificateList_DoCallback(certList, convert_cert, &pk11cb); - } else { - certList = nssList_Create(NULL, PR_FALSE); - if (!certList) { - return SECFailure; - } - (void *)nssTrustDomain_GetCertsFromCache(td, certList); - /* set the search criteria */ - search.callback = convert_and_cache_cert; - search.cbarg = &pk11cb; - search.cached = certList; - search.searchType = nssTokenSearchType_TokenOnly; - pk11cb.cached = certList; - nssrv = nssToken_TraverseCertificates(tok, NULL, &search); - if (nssrv == PR_SUCCESS) { - filter_list_for_token_certs(certList, tok); - nssrv = nssCertificateList_DoCallback(certList, - convert_cert, &pk11cb); - } - nssList_Clear(certList, cert_destructor); - nssList_Destroy(certList); + if (!nssToken_IsPresent(tok)) { + return SECSuccess; } - return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; -#endif -} - -static NSSCertificate * -filter_token_certs_DER(NSSToken *token, NSSDER *der) -{ - nssListIterator *certs; - NSSCertificate *cert, *rvCert; - PRStatus nssrv; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvCert = NULL; - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - if (nssItem_Equal(&cert->encoding, der, &nssrv)) { - rvCert = nssCertificate_AddRef(cert); - break; + collection = nssCertificateCollection_Create(td, NULL); + if (!collection) { + return SECFailure; + } + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) { + nssPKIObjectCollection_Destroy(collection); + return SECFailure; + } + (void *)nssTrustDomain_GetCertsFromCache(td, certList); + transfer_token_certs_to_collection(certList, tok, collection); + instances = nssToken_FindCertificates(tok, NULL, + tokenOnly, 0, &nssrv); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + nssList_Destroy(certList); + certs = nssPKIObjectCollection_GetCertificates(collection, + NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + if (certs) { + CERTCertificate *oldie; + NSSCertificate **cp; + for (cp = certs; *cp; cp++) { + oldie = STAN_GetCERTCertificate(*cp); + if ((*callback)(oldie, arg) != SECSuccess) { + nssrv = PR_FAILURE; + break; + } } + nssCertificateArray_Destroy(certs); } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - return rvCert; + return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; +#endif } /* @@ -2970,14 +2858,23 @@ PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert, return NULL; } } - if (!nssToken_SearchCerts(tok, NULL)) { - c = filter_token_certs_DER(tok, &derCert); - } else { - c = nssTrustDomain_GetCertByDERFromCache(td, &derCert); - if (!c) { - c = nssToken_FindCertificateByEncodedCertificate(tok, NULL, - &derCert, - nssTokenSearchType_TokenOnly); + c = NSSTrustDomain_FindCertificateByEncodedCertificate(td, &derCert); + if (c) { + PRBool isToken = PR_FALSE; + NSSToken **tp; + NSSToken **tokens = nssPKIObject_GetTokens(&c->object, NULL); + if (tokens) { + for (tp = tokens; *tp; tp++) { + if (*tp == tok) { + isToken = PR_TRUE; + break; + } + } + if (!isToken) { + NSSCertificate_Destroy(c); + c = NULL; + } + nssTokenArray_Destroy(tokens); } } if (c) { @@ -3348,12 +3245,16 @@ pk11ListCertCallback(CERTCertificate *cert, void *arg) CERTCertList *certList = listCertP->certList; CERTCertTrust *trust; PRBool isUnique = PR_FALSE; + PRBool isCA = PR_FALSE; char *nickname = NULL; unsigned int certType; if ((type == PK11CertListUnique) || (type == PK11CertListRootUnique)) { isUnique = PR_TRUE; } + if ((type == PK11CertListCA) || (type == PK11CertListRootUnique)) { + isCA = PR_TRUE; + } /* at this point the nickname is correct for the cert. save it for later */ if (!isUnique && cert->nickname) { nickname = PORT_ArenaStrdup(listCertP->certList->arena,cert->nickname); @@ -3397,7 +3298,7 @@ pk11ListCertCallback(CERTCertificate *cert, void *arg) } /* if we want CA certs and it ain't one, skip it */ - if( type == PK11CertListCA && (!CERT_IsCACert(newCert, &certType)) ) { + if( isCA && (!CERT_IsCACert(newCert, &certType)) ) { CERT_DestroyCertificate(newCert); return SECSuccess; } @@ -3440,7 +3341,18 @@ PK11_ListCerts(PK11CertListType type, void *pwarg) listCerts.certList = certList; pk11cb.callback = pk11ListCertCallback; pk11cb.arg = &listCerts; - NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb); + + /* authenticate to the slots */ + (void) pk11_TraverseAllSlots( NULL, NULL, pwarg); +#ifdef notdef + if (type == PK11CertListUser) { + NSSTrustDomain_TraverseUserCertificates(defaultTD, convert_cert &pk11cb); + } else { + NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb); + } +#else + NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb); +#endif return certList; #endif } @@ -3592,7 +3504,6 @@ PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname) int tsize = 0; int objCount = 0; CK_OBJECT_HANDLE *key_ids; - SECStatus status; SECKEYPublicKeyList *keys; int i,len; @@ -3619,7 +3530,9 @@ PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname) for (i=0; i < objCount ; i++) { SECKEYPublicKey *pubKey = PK11_ExtractPublicKey(slot,nullKey,key_ids[i]); - SECKEY_AddPublicKeyToListTail(keys, pubKey); + if (pubKey) { + SECKEY_AddPublicKeyToListTail(keys, pubKey); + } } PORT_Free(key_ids); @@ -3636,7 +3549,6 @@ PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) int tsize = 0; int objCount = 0; CK_OBJECT_HANDLE *key_ids; - SECStatus status; SECKEYPrivateKeyList *keys; int i,len; @@ -3677,6 +3589,7 @@ SECItem * PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, SECItem *name, int type, char **url) { +#ifdef NSS_CLASSIC CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; CK_ATTRIBUTE theTemplate[] = { { CKA_SUBJECT, NULL, 0 }, @@ -3710,9 +3623,6 @@ PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, /* loop through all the fortezza tokens */ for (le = list->head; le; le = le->next) { - if (le->slot->nssToken && !nssToken_HasCrls(le->slot->nssToken)) { - continue; - } crlh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize); if (crlh != CK_INVALID_HANDLE) { *slot = PK11_ReferenceSlot(le->slot); @@ -3759,12 +3669,68 @@ loser: } if (crlData[1].pValue) PORT_Free(crlData[1].pValue); return derCrl; +#else + NSSCRL **crls, **crlp, *crl; + NSSDER subject; + SECItem *rvItem; + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); + NSSITEM_FROM_SECITEM(&subject, name); + if (*slot) { + nssCryptokiObject **instances; + nssPKIObjectCollection *collection; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + NSSToken *token = PK11Slot_GetNSSToken(*slot); + collection = nssCRLCollection_Create(td, NULL); + if (!collection) { + return NULL; + } + instances = nssToken_FindCRLsBySubject(token, NULL, &subject, + tokenOnly, 0, NULL); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + } else { + crls = nssTrustDomain_FindCRLsBySubject(td, &subject); + } + if (!crls) { + return NULL; + } + crl = NULL; + for (crlp = crls; *crlp; crlp++) { + if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) || + ((*crlp)->isKRL && type != SEC_CRL_TYPE)) + { + crl = nssCRL_AddRef(*crlp); + break; + } + } + nssCRLArray_Destroy(crls); + if (!crl) { + return NULL; + } + *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot); + *crlHandle = crl->object.instances[0]->handle; + if (crl->url) { + *url = PORT_Strdup(crl->url); + } + rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size); + if (!rvItem) { + PORT_Free(*url); + nssCRL_Destroy(crl); + return NULL; + } + memcpy(rvItem->data, crl->encoding.data, crl->encoding.size); + nssCRL_Destroy(crl); + return rvItem; +#endif } CK_OBJECT_HANDLE PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, char *url, int type) { +#ifdef NSS_CLASSIC CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; CK_ATTRIBUTE theTemplate[] = { { CKA_SUBJECT, NULL, 0 }, @@ -3810,12 +3776,29 @@ PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, PK11_RestoreROSession(slot,rwsession); - if (slot->nssToken) { - nssToken_SetHasCrls(slot->nssToken); - } return crlh; -} +#else + NSSItem derCRL, derSubject; + NSSToken *token = PK11Slot_GetNSSToken(slot); + nssCryptokiObject *object; + PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE; + CK_OBJECT_HANDLE rvH; + NSSITEM_FROM_SECITEM(&derSubject, name); + NSSITEM_FROM_SECITEM(&derCRL, crl); + + object = nssToken_ImportCRL(token, NULL, + &derSubject, &derCRL, isKRL, url, PR_TRUE); + + if (object) { + rvH = object->handle; + nssCryptokiObject_Destroy(object); + } else { + rvH = CK_INVALID_HANDLE; + } + return rvH; +#endif +} /* @@ -3824,6 +3807,7 @@ PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, SECStatus SEC_DeletePermCRL(CERTSignedCrl *crl) { +#ifdef NSS_CLASSIC PK11SlotInfo *slot = crl->slot; CK_RV crv; @@ -3836,12 +3820,34 @@ SEC_DeletePermCRL(CERTSignedCrl *crl) crv = PK11_DestroyTokenObject(slot,crl->pkcs11ID); if (crv != CKR_OK) { PORT_SetError( PK11_MapError(crv) ); - goto loser; + return SECFailure; } crl->slot = NULL; PK11_FreeSlot(slot); -loser: return SECSuccess; +#else + PRStatus status; + NSSToken *token; + nssCryptokiObject *object; + PK11SlotInfo *slot = crl->slot; + + if (slot == NULL) { + /* shouldn't happen */ + PORT_SetError( SEC_ERROR_CRL_INVALID); + return SECFailure; + } + token = PK11Slot_GetNSSToken(slot); + + object = nss_ZNEW(NULL, nssCryptokiObject); + object->token = nssToken_AddRef(token); + object->handle = crl->pkcs11ID; + object->isTokenObject = PR_TRUE; + + status = nssToken_DeleteStoredObject(object); + + nssCryptokiObject_Destroy(object); + return (status == PR_SUCCESS) ? SECSuccess : SECFailure; +#endif } /* @@ -3966,6 +3972,7 @@ PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj, CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; CK_ATTRIBUTE *attrs = theTemplate; CK_SESSION_HANDLE rwsession; + PK11SlotInfo *free_slot = NULL; CK_RV crv; #ifdef DEBUG int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); @@ -3986,13 +3993,16 @@ PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj, PORT_Assert (realSize <= tsize); if (slot == NULL) { - slot = PK11_GetInternalKeySlot(); + free_slot = slot = PK11_GetInternalKeySlot(); /* we need to free the key slot in the end!!! */ } rwsession = PK11_GetRWSession(slot); if (rwsession == CK_INVALID_SESSION) { PORT_SetError(SEC_ERROR_READ_ONLY); + if (free_slot) { + PK11_FreeSlot(free_slot); + } return SECFailure; } @@ -4003,6 +4013,10 @@ PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj, } PK11_RestoreROSession(slot,rwsession); + + if (free_slot) { + PK11_FreeSlot(free_slot); + } return SECSuccess; } diff --git a/security/nss/lib/pk11wrap/pk11pars.c b/security/nss/lib/pk11wrap/pk11pars.c index 71ed7b0b7..b1602f1c8 100644 --- a/security/nss/lib/pk11wrap/pk11pars.c +++ b/security/nss/lib/pk11wrap/pk11pars.c @@ -40,6 +40,7 @@ #include "seccomon.h" #include "secmod.h" #include "secmodi.h" +#include "pki3hack.h" #include "pk11pars.h" @@ -144,6 +145,8 @@ SECMOD_CreateModule(char *library, char *moduleName, char *parameters, char *nss pk11_argSetNewCipherFlags(&mod->ssl[0],ciphers); if (ciphers) PORT_Free(ciphers); + secmod_PrivateModuleCount++; + return mod; } @@ -261,15 +264,16 @@ SECMOD_DeletePermDB(SECMODModule *module) } SECStatus -SECMOD_FreeModuleSpecList(SECMODModule *parent, char **moduleSpecList) +SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList) { - char ** index; - - for(index = moduleSpecList; *index; index++) { - PORT_Free(*index); + SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc; + char **retString; + if (func) { + retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE, + module->libraryParams,moduleSpecList); + if (retString != NULL) return SECSuccess; } - PORT_Free(moduleSpecList); - return SECSuccess; + return SECFailure; } /* diff --git a/security/nss/lib/pk11wrap/pk11pbe.c b/security/nss/lib/pk11wrap/pk11pbe.c index 71548a07a..5d828dba3 100644 --- a/security/nss/lib/pk11wrap/pk11pbe.c +++ b/security/nss/lib/pk11wrap/pk11pbe.c @@ -504,6 +504,7 @@ PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, SECItem mechItem; CK_PBE_PARAMS pbe_params; CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; + PK11SlotInfo *slot; PK11SymKey *symKey = NULL; unsigned char ivData[8]; @@ -567,8 +568,10 @@ PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, mechItem.len = sizeof(pbe_params); - symKey = PK11_RawPBEKeyGen(PK11_GetInternalSlot(),mechanism, + slot = PK11_GetInternalSlot(); + symKey = PK11_RawPBEKeyGen(slot,mechanism, &mechItem, pwitem, PR_FALSE, NULL); + PK11_FreeSlot(slot); if (symKey != NULL) { if (bitGenPurpose == pbeBitGenCipherIV) { /* NOTE: this assumes that bitsNeeded is a multiple of 8! */ @@ -615,6 +618,7 @@ SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) SECItem *iv = NULL; SECStatus rv; int iv_len; + PK11SlotInfo *slot; PK11SymKey *symKey; rv = pbe_PK11AlgidToParam(algid,&mechItem); @@ -626,8 +630,10 @@ SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) iv_len = PK11_GetIVLength(mechanism); pbe_params = (CK_PBE_PARAMS_PTR)mechItem.data; - symKey = PK11_RawPBEKeyGen(PK11_GetInternalSlot(),mechanism, + slot = PK11_GetInternalSlot(); + symKey = PK11_RawPBEKeyGen(slot,mechanism, &mechItem, pwitem, faulty3DES,NULL); + PK11_FreeSlot(slot); if (symKey) { SECItem tmp; diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index b77b718fb..7955a203e 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -161,7 +161,6 @@ static PK11SymKey * pk11_getKeyFromList(PK11SlotInfo *slot) { PK11SymKey *symKey = NULL; - PK11_USE_THREADS(PZ_Lock(slot->freeListLock);) if (slot->freeSymKeysHead) { symKey = slot->freeSymKeysHead; @@ -180,11 +179,6 @@ pk11_getKeyFromList(PK11SlotInfo *slot) { if (symKey == NULL) { return NULL; } - symKey->refLock = PZ_NewLock(nssILockRefLock); - if (symKey->refLock == NULL) { - PORT_Free(symKey); - return NULL; - } symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner); symKey->next = NULL; return symKey; @@ -199,7 +193,6 @@ PK11_CleanKeyList(PK11SlotInfo *slot) symKey = slot->freeSymKeysHead; slot->freeSymKeysHead = symKey->next; pk11_CloseSession(slot, symKey->session,symKey->sessionOwner); - PK11_USE_THREADS(PZ_DestroyLock(symKey->refLock);) PORT_Free(symKey); }; return; @@ -243,16 +236,10 @@ PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx) void PK11_FreeSymKey(PK11SymKey *symKey) { - PRBool destroy = PR_FALSE; PK11SlotInfo *slot; PRBool freeit = PR_TRUE; - PK11_USE_THREADS(PZ_Lock(symKey->refLock);) - if (symKey->refCount-- == 1) { - destroy= PR_TRUE; - } - PK11_USE_THREADS(PZ_Unlock(symKey->refLock);) - if (destroy) { + if (PR_AtomicDecrement(&symKey->refCount) == 0) { if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) { pk11_EnterKeyMonitor(symKey); (void) PK11_GETTAB(symKey->slot)-> @@ -266,17 +253,16 @@ PK11_FreeSymKey(PK11SymKey *symKey) slot = symKey->slot; PK11_USE_THREADS(PZ_Lock(slot->freeListLock);) if (slot->keyCount < slot->maxKeyCount) { - symKey->next = slot->freeSymKeysHead; - slot->freeSymKeysHead = symKey; - slot->keyCount++; - symKey->slot = NULL; - freeit = PR_FALSE; + symKey->next = slot->freeSymKeysHead; + slot->freeSymKeysHead = symKey; + slot->keyCount++; + symKey->slot = NULL; + freeit = PR_FALSE; } PK11_USE_THREADS(PZ_Unlock(slot->freeListLock);) if (freeit) { pk11_CloseSession(symKey->slot, symKey->session, symKey->sessionOwner); - PK11_USE_THREADS(PZ_DestroyLock(symKey->refLock);) PORT_Free(symKey); } PK11_FreeSlot(slot); @@ -286,9 +272,7 @@ PK11_FreeSymKey(PK11SymKey *symKey) PK11SymKey * PK11_ReferenceSymKey(PK11SymKey *symKey) { - PK11_USE_THREADS(PZ_Lock(symKey->refLock);) - symKey->refCount++; - PK11_USE_THREADS(PZ_Unlock(symKey->refLock);) + PR_AtomicIncrement(&symKey->refCount); return symKey; } @@ -1568,7 +1552,6 @@ pk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, PK11_ExitSlotMonitor(slot); PORT_SetError( PK11_MapError(crv) ); PORT_Free( ciphertext ); - PK11_FreeSlot(slot); return SECFailure; } @@ -1591,7 +1574,6 @@ pk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, if( crv != CKR_OK ) { PORT_SetError( PK11_MapError(crv) ); - PK11_FreeSlot(slot); return SECFailure; } @@ -1602,7 +1584,6 @@ pk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, PAIRWISE_MESSAGE_LENGTH ) != 0 ) ) { /* Set error to Bad PUBLIC Key. */ PORT_SetError( SEC_ERROR_BAD_KEY ); - PK11_FreeSlot(slot); return SECFailure; } } @@ -3207,12 +3188,14 @@ PK11_PubEncryptRaw(SECKEYPublicKey *key, unsigned char *enc, if (crv != CKR_OK) { if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); pk11_CloseSession(slot,session,owner); + PK11_FreeSlot(slot); PORT_SetError( PK11_MapError(crv) ); return SECFailure; } crv = PK11_GETTAB(slot)->C_Encrypt(session,data,dataLen,enc,&out); if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); pk11_CloseSession(slot,session,owner); + PK11_FreeSlot(slot); if (crv != CKR_OK) { PORT_SetError( PK11_MapError(crv) ); return SECFailure; @@ -4463,7 +4446,7 @@ PK11_ExportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, SECOidTag algTag, SECItem *pwitem, CERTCertificate *cert, int iteration, void *wincx) { SECKEYEncryptedPrivateKeyInfo *epki = NULL; - SECKEYPrivateKey *pk; + SECKEYPrivateKey *pk = NULL; PRArenaPool *arena = NULL; SECAlgorithmID *algid; CK_MECHANISM_TYPE mechanism; @@ -4580,6 +4563,10 @@ loser: PK11_FreeSymKey(key); } + if (pk != NULL) { + SECKEY_DestroyPrivateKey(pk); + } + if(rv == SECFailure) { if(arena != NULL) { PORT_FreeArena(arena, PR_TRUE); @@ -4771,8 +4758,11 @@ PK11_WrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey, privSlot = int_slot; /* The private key has a new home */ newPrivKey = pk11_loadPrivKey(privSlot,privKey,NULL,PR_FALSE,PR_FALSE); + /* newPrivKey has allocated its own reference to the slot, so it's + * safe until we destroy newPrivkey. + */ + PK11_FreeSlot(int_slot); if (newPrivKey == NULL) { - PK11_FreeSlot (int_slot); return SECFailure; } privKey = newPrivKey; diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index cd2d29bd4..6d93bc650 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -54,6 +54,7 @@ #include "dev.h" #include "dev3hack.h" #include "pki3hack.h" +#include "pkim.h" /************************************************************* @@ -727,10 +728,6 @@ PK11_Logout(PK11SlotInfo *slot) PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_Logout(slot->session); PK11_ExitSlotMonitor(slot); - if (slot->nssToken && !PK11_IsFriendly(slot)) { - /* If the slot certs are not public readable, destroy them */ - nssToken_DestroyCertList(slot->nssToken, PR_TRUE); - } if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; @@ -1146,10 +1143,9 @@ PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) } if (rv == SECSuccess) { rv = pk11_CheckVerifyTest(slot); - if (rv == SECSuccess && slot->nssToken && !PK11_IsFriendly(slot)) { - /* notify stan about the login if certs are not public readable */ - nssToken_LoadCerts(slot->nssToken); - nssToken_UpdateTrustForCerts(slot->nssToken); + if (!PK11_IsFriendly(slot)) { + nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain, + slot->nssToken); } } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD); return rv; @@ -1571,7 +1567,10 @@ PK11_VerifySlotMechanisms(PK11SlotInfo *slot) mechList = (CK_MECHANISM_TYPE *) PORT_Alloc(count *sizeof(CK_MECHANISM_TYPE)); alloced = PR_TRUE; - if (mechList == NULL) return PR_FALSE; + if (mechList == NULL) { + PK11_FreeSlot(intern); + return PR_FALSE; + } } /* get the list */ if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); @@ -1718,6 +1717,11 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) slot->protectedAuthPath = ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ? PR_TRUE : PR_FALSE); + /* on some platforms Active Card incorrectly sets the + * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */ + if (slot->isActiveCard) { + slot->protectedAuthPath = PR_FALSE; + } tmp = PK11_MakeString(NULL,slot->token_name, (char *)tokenInfo.label, sizeof(tokenInfo.label)); slot->minPassword = tokenInfo.ulMinPinLen; @@ -1826,6 +1830,7 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) random_bytes, sizeof(random_bytes)); PK11_ExitSlotMonitor(slot); } + PK11_FreeSlot(int_slot); } } @@ -1891,6 +1896,9 @@ PK11_InitSlot(SECMODModule *mod,CK_SLOT_ID slotID,PK11SlotInfo *slot) tmp = PK11_MakeString(NULL,slot->slot_name, (char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription)); slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT); +#define ACTIVE_CARD "ActivCard SA" + slot->isActiveCard = (PRBool)(PORT_Strncmp((char *)slotInfo.manufacturerID, + ACTIVE_CARD, sizeof(ACTIVE_CARD)-1) == 0); if ((slotInfo.flags & CKF_REMOVABLE_DEVICE) == 0) { slot->isPerm = PR_TRUE; /* permanment slots must have the token present always */ @@ -4356,12 +4364,18 @@ PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, if (pk11_isAllZero(pPBEparams->pInitVector,iv_len)) { SECItem param; PK11SymKey *symKey; + PK11SlotInfo *intSlot = PK11_GetInternalSlot(); + + if (intSlot == NULL) { + return CKR_DEVICE_ERROR; + } param.data = pPBEMechanism->pParameter; param.len = pPBEMechanism->ulParameterLen; - symKey = PK11_RawPBEKeyGen(PK11_GetInternalSlot(), + symKey = PK11_RawPBEKeyGen(intSlot, pPBEMechanism->mechanism, ¶m, pbe_pwd, faulty3DES, NULL); + PK11_FreeSlot(intSlot); if (symKey== NULL) { return CKR_DEVICE_ERROR; /* sigh */ } diff --git a/security/nss/lib/pk11wrap/pk11util.c b/security/nss/lib/pk11wrap/pk11util.c index 67b439125..11673d9f6 100644 --- a/security/nss/lib/pk11wrap/pk11util.c +++ b/security/nss/lib/pk11wrap/pk11util.c @@ -39,6 +39,7 @@ #include "secmodi.h" #include "pk11func.h" #include "pki3hack.h" +#include "secerr.h" /* these are for displaying error messages */ @@ -47,13 +48,17 @@ static SECMODModuleList *modulesDB = NULL; static SECMODModuleList *modulesUnload = NULL; static SECMODModule *internalModule = NULL; static SECMODModule *defaultDBModule = NULL; +static SECMODModule *pendingModule = NULL; static SECMODListLock *moduleLock = NULL; +int secmod_PrivateModuleCount = 0; + extern PK11DefaultArrayEntry PK11_DefaultArray[]; extern int num_pk11_default_mechanisms; -void SECMOD_Init() { +void +SECMOD_Init() { /* don't initialize twice */ if (moduleLock) return; @@ -62,7 +67,8 @@ void SECMOD_Init() { } -void SECMOD_Shutdown() { +SECStatus +SECMOD_Shutdown() { /* destroy the lock */ if (moduleLock) { SECMOD_DestroyListLock(moduleLock); @@ -73,6 +79,13 @@ void SECMOD_Shutdown() { SECMOD_DestroyModule(internalModule); internalModule = NULL; } + + /* free the default database module */ + if (defaultDBModule) { + SECMOD_DestroyModule(defaultDBModule); + defaultDBModule = NULL; + } + /* destroy the list */ if (modules) { SECMOD_DestroyModuleList(modules); @@ -91,6 +104,13 @@ void SECMOD_Shutdown() { /* make all the slots and the lists go away */ PK11_DestroySlotLists(); + +#ifdef DEBUG + if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) { + PORT_Assert(secmod_PrivateModuleCount == 0); + } +#endif + return (secmod_PrivateModuleCount == 0) ? SECSuccess : SECFailure; } @@ -285,6 +305,11 @@ SECMOD_DeleteInternalModule(char *name) { SECMODModuleList **mlpp; SECStatus rv = SECFailure; + if (pendingModule) { + PORT_SetError(SEC_ERROR_MODULE_STUCK); + return rv; + } + SECMOD_GetWriteLock(moduleLock); for(mlpp = &modules,mlp = modules; mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) { @@ -329,12 +354,12 @@ SECMOD_DeleteInternalModule(char *name) { } newModule->libraryParams = PORT_ArenaStrdup(newModule->arena,mlp->module->libraryParams); - oldModule = internalModule; + pendingModule = oldModule = internalModule; internalModule = NULL; SECMOD_DestroyModule(oldModule); SECMOD_DeletePermDB(mlp->module); SECMOD_DestroyModuleListElement(mlp); - internalModule = SECMOD_ReferenceModule(newModule); + internalModule = newModule; /* adopt the module */ SECMOD_AddModule(internalModule); } return rv; @@ -434,6 +459,10 @@ SECStatus SECMOD_AddNewModuleEx(char* moduleName, char* dllPath, module = SECMOD_CreateModule(dllPath,moduleName, modparms, nssparms); + if (module == NULL) { + return result; + } + if (module->dllName != NULL) { if (module->dllName[0] != 0) { result = SECMOD_AddModule(module); @@ -485,8 +514,8 @@ SECStatus SECMOD_UpdateModule(SECMODModule *module) result = SECMOD_DeletePermDB(module); if (result == SECSuccess) { - } result = SECMOD_AddPermDB(module); + } return result; } @@ -590,6 +619,13 @@ SECMOD_DestroyModule(SECMODModule *module) { if (!willfree) { return; } + + if (module->parent != NULL) { + SECMODModule *parent = module->parent; + /* paranoia, don't loop forever if the modules are looped */ + module->parent = NULL; + SECMOD_DestroyModule(parent); + } /* slots can't really disappear until our module starts freeing them, * so this check is safe */ @@ -627,11 +663,17 @@ SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) { PK11_USE_THREADS(PZ_Unlock((PZLock *)module->refLock);) if (!willfree) return; } + + if (module == pendingModule) { + pendingModule = NULL; + } + if (module->loaded) { SECMOD_UnloadModule(module); } PK11_USE_THREADS(PZ_DestroyLock((PZLock *)module->refLock);) PORT_FreeArena(module->arena,PR_FALSE); + secmod_PrivateModuleCount--; } /* destroy a list element @@ -661,3 +703,8 @@ SECMOD_DestroyModuleList(SECMODModuleList *list) { for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ; } +PRBool +SECMOD_CanDeleteInternalModule(void) +{ + return (PRBool) pendingModule == NULL; +} diff --git a/security/nss/lib/pk11wrap/secmod.h b/security/nss/lib/pk11wrap/secmod.h index 303e3fe58..64461a112 100644 --- a/security/nss/lib/pk11wrap/secmod.h +++ b/security/nss/lib/pk11wrap/secmod.h @@ -91,7 +91,7 @@ SECStatus SECMOD_UnloadUserModule(SECMODModule *mod); SECMODModule * SECMOD_CreateModule(char *lib, char *name, char *param, char *nss); -extern void SECMOD_Shutdown(void); +extern SECStatus SECMOD_Shutdown(void); /* Module Management */ @@ -117,6 +117,7 @@ extern void SECMOD_ReleaseWriteLock(SECMODListLock *); extern SECMODModule *SECMOD_FindModule(char *name); extern SECStatus SECMOD_DeleteModule(char *name, int *type); extern SECStatus SECMOD_DeleteInternalModule(char *name); +extern PRBool SECMOD_CanDeleteInternalModule(void); extern SECStatus SECMOD_AddNewModule(char* moduleName, char* dllPath, unsigned long defaultMechanismFlags, unsigned long cipherEnableFlags); diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h index 9e78addb4..050f7de4f 100644 --- a/security/nss/lib/pk11wrap/secmodi.h +++ b/security/nss/lib/pk11wrap/secmodi.h @@ -57,6 +57,8 @@ SEC_BEGIN_PROTOS extern SECStatus SECMOD_DeletePermDB(SECMODModule *module); extern SECStatus SECMOD_AddPermDB(SECMODModule *module); +extern int secmod_PrivateModuleCount; + extern void SECMOD_Init(void); /* list managment */ diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h index 9d3919903..232b58c7a 100644 --- a/security/nss/lib/pk11wrap/secmodti.h +++ b/security/nss/lib/pk11wrap/secmodti.h @@ -130,6 +130,7 @@ struct PK11SlotInfoStr { PRBool hasRSAInfo; CK_FLAGS RSAInfoFlags; PRBool protectedAuthPath; + PRBool isActiveCard; /* for Stan */ NSSToken *nssToken; }; @@ -145,8 +146,7 @@ struct PK11SymKeyStr { SECItem data; /* raw key data if available */ CK_SESSION_HANDLE session; PRBool sessionOwner; - int refCount; /* number of references to this key */ - PZLock *refLock; + PRInt32 refCount; /* number of references to this key */ int size; /* key size in bytes */ PK11Origin origin; /* where this key came from (see def in secmodt.h) */ diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index 051428575..ca5017cc5 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -1093,7 +1093,7 @@ p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len) return -1; } - if (!p12cxt->buffer || ((p12cxt->filesize-p12cxt->currentpos)<len) ) { + if (!p12cxt->buffer || ((p12cxt->filesize-p12cxt->currentpos)<(long)len) ) { /* trying to read past the end of the buffer */ toread = p12cxt->filesize-p12cxt->currentpos; } @@ -1111,7 +1111,7 @@ p12u_DigestWrite(void *arg, unsigned char *buf, unsigned long len) return -1; } - if (p12cxt->currentpos+len > p12cxt->filesize) { + if (p12cxt->currentpos+(long)len > p12cxt->filesize) { p12cxt->filesize = p12cxt->currentpos + len; } else { @@ -1191,7 +1191,8 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx, p12dcx->arena = arena; p12dcx->pwitem = pwitem; - p12dcx->slot = (slot ? slot : PK11_GetInternalKeySlot()); + p12dcx->slot = (slot ? PK11_ReferenceSlot(slot) + : PK11_GetInternalKeySlot()); p12dcx->wincx = wincx; #ifdef IS_LITTLE_ENDIAN p12dcx->swapUnicodeBytes = PR_TRUE; @@ -1201,12 +1202,6 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx, p12dcx->errorValue = 0; p12dcx->error = PR_FALSE; - /* a slot is *required */ - if(!slot) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - /* start the decoding of the PFX and set the notify proc * for the PFX item. */ @@ -1214,6 +1209,7 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx, sec_PKCS12PFXItemTemplate); if(!p12dcx->pfxDcx) { PORT_SetError(SEC_ERROR_NO_MEMORY); + PK11_FreeSlot(p12dcx->slot); goto loser; } @@ -1279,14 +1275,15 @@ static SECStatus sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx) { SECStatus rv = SECFailure; + SECStatus lrv; SECItem hmacRes; unsigned char buf[IN_BUF_LEN]; unsigned int bufLen; int iteration; PK11Context *pk11cx = NULL; + PK11SymKey *symKey = NULL; + SECItem *params = NULL; SECItem ignore = {0}; - PK11SymKey *symKey; - SECItem *params; SECOidTag algtag; CK_MECHANISM_TYPE integrityMech; @@ -1318,15 +1315,18 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx) symKey = PK11_KeyGen(NULL, integrityMech, params, 20, NULL); PK11_DestroyPBEParams(params); + params = NULL; if (!symKey) goto loser; /* init hmac */ pk11cx = PK11_CreateContextBySymKey(sec_pkcs12_algtag_to_mech(algtag), CKA_SIGN, symKey, &ignore); if(!pk11cx) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; + goto loser; + } + lrv = PK11_DigestBegin(pk11cx); + if (lrv == SECFailure ) { + goto loser; } - rv = PK11_DigestBegin(pk11cx); /* try to open the data for readback */ if(p12dcx->dOpen && ((*p12dcx->dOpen)(p12dcx->dArg, PR_TRUE) @@ -1346,14 +1346,20 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx) goto loser; } - rv = PK11_DigestOp(pk11cx, buf, bytesRead); + lrv = PK11_DigestOp(pk11cx, buf, bytesRead); + if (lrv == SECFailure) { + goto loser; + } if(bytesRead < IN_BUF_LEN) { break; } } /* finish the hmac context */ - rv = PK11_DigestFinal(pk11cx, buf, &bufLen, IN_BUF_LEN); + lrv = PK11_DigestFinal(pk11cx, buf, &bufLen, IN_BUF_LEN); + if (lrv == SECFailure ) { + goto loser; + } hmacRes.data = buf; hmacRes.len = bufLen; @@ -1375,6 +1381,12 @@ loser: if(pk11cx) { PK11_DestroyContext(pk11cx, PR_TRUE); } + if (params) { + PK11_DestroyPBEParams(params); + } + if (symKey) { + PK11_FreeSymKey(symKey); + } return rv; } @@ -1460,6 +1472,11 @@ SEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx) p12dcx->hmacDcx = NULL; } + if(p12dcx->slot) { + PK11_FreeSlot(p12dcx->slot); + p12dcx->slot = NULL; + } + if(p12dcx->arena) { PORT_FreeArena(p12dcx->arena, PR_TRUE); } @@ -2223,7 +2240,7 @@ sec_pkcs12_validate_cert(sec_PKCS12SafeBag *cert, } cert->noInstall = PR_FALSE; - cert->removeExisting = PR_FALSE; + cert->unused = PR_FALSE; cert->problem = PR_FALSE; cert->error = 0; @@ -2236,26 +2253,7 @@ sec_pkcs12_validate_cert(sec_PKCS12SafeBag *cert, return; } - testCert = PK11_FindCertFromDERCert(cert->slot, leafCert, wincx); CERT_DestroyCertificate(leafCert); - /* if we can't find the certificate through the PKCS11 interface, - * we should check the cert database directly, if we are - * importing to an internal slot. - */ - if(!testCert && PK11_IsInternal(cert->slot)) { - testCert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), - &cert->safeBagContent.certBag->value.x509Cert); - } - - if(testCert) { - if(!testCert->nickname) { - cert->removeExisting = PR_TRUE; - } - CERT_DestroyCertificate(testCert); - if(cert->noInstall && !cert->removeExisting) { - return; - } - } sec_pkcs12_validate_cert_nickname(cert, key, nicknameCb, wincx); } @@ -2303,59 +2301,6 @@ sec_pkcs12_validate_key_by_cert(sec_PKCS12SafeBag *cert, sec_PKCS12SafeBag *key, } static SECStatus -sec_pkcs12_remove_existing_cert(sec_PKCS12SafeBag *cert, - void *wincx) -{ - SECItem *derCert = NULL; - CERTCertificate *tempCert = NULL; - CK_OBJECT_HANDLE certObj; - PRBool removed = PR_FALSE; - - if(!cert) { - return SECFailure; - } - - PORT_Assert(cert->removeExisting); - - cert->removeExisting = PR_FALSE; - derCert = &cert->safeBagContent.certBag->value.x509Cert; - tempCert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); - if(!tempCert) { - return SECFailure; - } - - certObj = PK11_FindCertInSlot(cert->slot, tempCert, wincx); - CERT_DestroyCertificate(tempCert); - tempCert = NULL; - - if(certObj != CK_INVALID_HANDLE) { - PK11_DestroyObject(cert->slot, certObj); - removed = PR_TRUE; - } else if(PK11_IsInternal(cert->slot)) { - tempCert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), derCert); - if(tempCert) { - if(SEC_DeletePermCertificate(tempCert) == SECSuccess) { - removed = PR_TRUE; - } - CERT_DestroyCertificate(tempCert); - tempCert = NULL; - } - } - - if(!removed) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - cert->noInstall = PR_TRUE; - } - - if(tempCert) { - CERT_DestroyCertificate(tempCert); - } - - return ((removed) ? SECSuccess : SECFailure); -} - -static SECStatus sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx) { SECItem *derCert, *nickName; @@ -2371,15 +2316,8 @@ sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx) } derCert = &cert->safeBagContent.certBag->value.x509Cert; - if(cert->removeExisting) { - if(sec_pkcs12_remove_existing_cert(cert, wincx) - != SECSuccess) { - return SECFailure; - } - cert->removeExisting = PR_FALSE; - } - PORT_Assert(!cert->problem && !cert->removeExisting && !cert->noInstall); + PORT_Assert(!cert->problem && !cert->noInstall); nickName = sec_pkcs12_get_nickname(cert); if(nickName) { @@ -2389,7 +2327,8 @@ sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx) if(keyExists) { CERTCertificate *newCert; - newCert = CERT_DecodeDERCertificate( derCert, PR_FALSE, NULL); + newCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + derCert, NULL, PR_FALSE, PR_FALSE); if(!newCert) { if(nickName) SECITEM_ZfreeItem(nickName, PR_TRUE); cert->error = SEC_ERROR_NO_MEMORY; @@ -2424,12 +2363,6 @@ sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECItem *publicValue, return SECFailure; } - if(key->removeExisting) { - key->problem = PR_TRUE; - key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; - return SECFailure; - } - if(key->problem || key->noInstall) { return SECSuccess; } @@ -2571,7 +2504,9 @@ SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx) CERTCertificate *tempCert = NULL; if (derCert == NULL) continue; - tempCert=CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL); + tempCert=CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + derCert, NULL, + PR_FALSE, PR_TRUE); if (tempCert) { CERT_AddCertToListTail(certList,tempCert); @@ -3312,7 +3247,7 @@ sec_PKCS12ConvertOldSafeToNew(PRArenaPool *arena, PK11SlotInfo *slot, } p12dcx->arena = arena; - p12dcx->slot = slot; + p12dcx->slot = PK11_ReferenceSlot(slot); p12dcx->wincx = wincx; p12dcx->error = PR_FALSE; p12dcx->swapUnicodeBytes = swapUnicode; diff --git a/security/nss/lib/pkcs12/p12e.c b/security/nss/lib/pkcs12/p12e.c index 9f9a92cea..1b86a49ac 100644 --- a/security/nss/lib/pkcs12/p12e.c +++ b/security/nss/lib/pkcs12/p12e.c @@ -194,7 +194,7 @@ SEC_PKCS12CreateExportContext(SECKEYGetPasswordKey pwfn, void *pwfnarg, p12ctxt->integrityEnabled = PR_FALSE; p12ctxt->arena = arena; p12ctxt->wincx = wincx; - p12ctxt->slot = (slot) ? slot : PK11_GetInternalSlot(); + p12ctxt->slot = (slot) ? PK11_ReferenceSlot(slot) : PK11_GetInternalSlot(); return p12ctxt; @@ -352,7 +352,7 @@ SEC_PKCS12CreatePasswordPrivSafe(SEC_PKCS12ExportContext *p12ctxt, { SEC_PKCS12SafeInfo *safeInfo = NULL; void *mark = NULL; - PK11SlotInfo *slot; + PK11SlotInfo *slot = NULL; SECAlgorithmID *algId; SECItem uniPwitem = {siBuffer, NULL, 0}; @@ -393,7 +393,7 @@ SEC_PKCS12CreatePasswordPrivSafe(SEC_PKCS12ExportContext *p12ctxt, } /* generate the encryption key */ - slot = p12ctxt->slot; + slot = PK11_ReferenceSlot(p12ctxt->slot); if(!slot) { slot = PK11_GetInternalKeySlot(); if(!slot) { @@ -419,9 +419,16 @@ SEC_PKCS12CreatePasswordPrivSafe(SEC_PKCS12ExportContext *p12ctxt, SECITEM_ZfreeItem(&uniPwitem, PR_FALSE); } PORT_ArenaUnmark(p12ctxt->arena, mark); + + if (slot) { + PK11_FreeSlot(slot); + } return safeInfo; loser: + if (slot) { + PK11_FreeSlot(slot); + } if(safeInfo->cinfo) { SEC_PKCS7DestroyContentInfo(safeInfo->cinfo); } @@ -1285,7 +1292,7 @@ SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *sa /* extract the key encrypted */ SECKEYEncryptedPrivateKeyInfo *epki = NULL; - PK11SlotInfo *slot = p12ctxt->slot; + PK11SlotInfo *slot = NULL; if(!sec_pkcs12_convert_item_to_unicode(p12ctxt->arena, &uniPwitem, pwitem, PR_TRUE, PR_TRUE, PR_TRUE)) { @@ -1296,14 +1303,14 @@ SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *sa /* we want to make sure to take the key out of the key slot */ if(PK11_IsInternal(p12ctxt->slot)) { slot = PK11_GetInternalKeySlot(); + } else { + slot = PK11_ReferenceSlot(p12ctxt->slot); } epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm, &uniPwitem, cert, 1, p12ctxt->wincx); - if(PK11_IsInternal(p12ctxt->slot)) { - PK11_FreeSlot(slot); - } + PK11_FreeSlot(slot); keyItem = PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECKEYEncryptedPrivateKeyInfo)); @@ -1409,7 +1416,8 @@ SEC_PKCS12AddDERCertAndEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, mark = PORT_ArenaMark(p12ctxt->arena); - cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); + cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + derCert, NULL, PR_FALSE, PR_FALSE); if(!cert) { PORT_ArenaRelease(p12ctxt->arena, mark); PORT_SetError(SEC_ERROR_NO_MEMORY); @@ -1719,6 +1727,8 @@ sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp) p12enc->hmacCx = PK11_CreateContextBySymKey( sec_pkcs12_algtag_to_mech(p12exp->integrityInfo.pwdInfo.algorithm), CKA_SIGN, symKey, &ignore); + + PK11_FreeSymKey(symKey); if(!p12enc->hmacCx) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; @@ -2137,6 +2147,8 @@ SEC_PKCS12DestroyExportContext(SEC_PKCS12ExportContext *p12ecx) } } + PK11_FreeSlot(p12ecx->slot); + PORT_FreeArena(p12ecx->arena, PR_TRUE); } diff --git a/security/nss/lib/pkcs12/p12t.h b/security/nss/lib/pkcs12/p12t.h index 6b9d3da1b..74e803c60 100644 --- a/security/nss/lib/pkcs12/p12t.h +++ b/security/nss/lib/pkcs12/p12t.h @@ -111,7 +111,7 @@ struct sec_PKCS12SafeBagStr { unsigned int nAttribs; /* used for validation/importing */ - PRBool problem, noInstall, validated, hasKey, removeExisting, installed; + PRBool problem, noInstall, validated, hasKey, unused, installed; int error; PRBool swapUnicodeBytes; diff --git a/security/nss/lib/pkcs7/certread.c b/security/nss/lib/pkcs7/certread.c index 073a9e545..672e3b132 100644 --- a/security/nss/lib/pkcs7/certread.c +++ b/security/nss/lib/pkcs7/certread.c @@ -162,7 +162,8 @@ CERT_ConvertAndDecodeCertificate(char *certstr) if (rv != SECSuccess) return NULL; - cert = CERT_DecodeDERCertificate(&der, PR_TRUE, NULL); + cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + &der, NULL, PR_FALSE, PR_TRUE); PORT_Free(der.data); return cert; @@ -528,7 +529,9 @@ CERT_DecodeCertFromPackage(char *certbuf, int certlen) rv = CERT_DecodeCertPackage(certbuf, certlen, collect_certs, (void *)&collectArgs); if ( rv == SECSuccess ) { - cert = CERT_DecodeDERCertificate(&collectArgs.cert, PR_TRUE, NULL); + cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + &collectArgs.cert, NULL, + PR_FALSE, PR_TRUE); } PORT_FreeArena(collectArgs.arena, PR_FALSE); diff --git a/security/nss/lib/pki/Makefile b/security/nss/lib/pki/Makefile index bfe27629c..4cbbfed70 100644 --- a/security/nss/lib/pki/Makefile +++ b/security/nss/lib/pki/Makefile @@ -34,11 +34,7 @@ MAKEFILE_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$ $Name$" include manifest.mn include $(CORE_DEPTH)/coreconf/config.mk -ifdef PURE_STAN_BUILD include config.mk -else -include config34.mk -endif include $(CORE_DEPTH)/coreconf/rules.mk export:: private_export diff --git a/security/nss/lib/pki/certdecode.c b/security/nss/lib/pki/certdecode.c index fbf0c1d67..cac766496 100644 --- a/security/nss/lib/pki/certdecode.c +++ b/security/nss/lib/pki/certdecode.c @@ -43,78 +43,6 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "pkim.h" #endif /* PKIM_H */ -/* XXX - * move this to a more appropriate location - */ -NSS_IMPLEMENT PRStatus -nssPKIObject_Initialize -( - struct nssPKIObjectBaseStr *object, - NSSArena *arena, - NSSTrustDomain *td, - NSSCryptoContext *cc -) -{ - object->arena = arena; - object->trustDomain = td; - object->cryptoContext = cc; - object->lock = PZ_NewLock(nssILockOther); - if (!object->lock) { - return PR_FAILURE; - } - object->instanceList = nssList_Create(arena, PR_TRUE); - if (!object->instanceList) { - PZ_DestroyLock(object->lock); - return PR_FAILURE; - } - object->instances = nssList_CreateIterator(object->instanceList); - if (!object->instances) { - nssList_Destroy(object->instanceList); - PZ_DestroyLock(object->lock); - return PR_FAILURE; - } - object->refCount = 1; - return PR_SUCCESS; -} - -/* XXX - * move this to a more appropriate location - */ -NSS_IMPLEMENT void -nssPKIObject_AddRef -( - struct nssPKIObjectBaseStr *object -) -{ - PZ_Lock(object->lock); - object->refCount++; - PZ_Unlock(object->lock); -} - -/* XXX - * move this to a more appropriate location - */ -NSS_IMPLEMENT PRBool -nssPKIObject_Destroy -( - struct nssPKIObjectBaseStr *object -) -{ - PRUint32 refCount; - PZ_Lock(object->lock); - PORT_Assert(object->refCount > 0); - refCount = --object->refCount; - PZ_Unlock(object->lock); - if (refCount == 0) { - PZ_DestroyLock(object->lock); - nssListIterator_Destroy(object->instances); - nssList_Destroy(object->instanceList); - nssArena_Destroy(object->arena); - return PR_TRUE; - } - return PR_FALSE; -} - #ifdef NSS_3_4_CODE /* This is defined in nss3hack.c */ NSS_EXTERN nssDecodedCert * @@ -194,39 +122,3 @@ nssDecodedCert_Destroy return PR_FAILURE; } -/* Of course none of this belongs here */ - -/* how bad would it be to have a static now sitting around, updated whenever - * this was called? would avoid repeated allocs... - */ -NSS_IMPLEMENT NSSTime * -NSSTime_Now -( - NSSTime *timeOpt -) -{ - return NSSTime_SetPRTime(timeOpt, PR_Now()); -} - -NSS_IMPLEMENT NSSTime * -NSSTime_SetPRTime -( - NSSTime *timeOpt, - PRTime prTime -) -{ - NSSTime *rvTime; - rvTime = (timeOpt) ? timeOpt : nss_ZNEW(NULL, NSSTime); - rvTime->prTime = prTime; - return rvTime; -} - -NSS_IMPLEMENT PRTime -NSSTime_GetPRTime -( - NSSTime *time -) -{ - return time->prTime; -} - diff --git a/security/nss/lib/pki/certificate.c b/security/nss/lib/pki/certificate.c index f9dc9a7e3..913fe559d 100644 --- a/security/nss/lib/pki/certificate.c +++ b/security/nss/lib/pki/certificate.c @@ -61,6 +61,40 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; extern const NSSError NSS_ERROR_NOT_FOUND; +/* Creates a certificate from a base object */ +NSS_IMPLEMENT NSSCertificate * +nssCertificate_Create +( + nssPKIObject *object +) +{ + PRStatus status; + NSSCertificate *rvCert; + /* mark? */ + NSSArena *arena = object->arena; + PR_ASSERT(object->instances != NULL && object->numInstances > 0); + rvCert = nss_ZNEW(arena, NSSCertificate); + if (!rvCert) { + return (NSSCertificate *)NULL; + } + rvCert->object = *object; + /* XXX should choose instance based on some criteria */ + status = nssCryptokiCertificate_GetAttributes(object->instances[0], + NULL, /* XXX sessionOpt */ + arena, + &rvCert->type, + &rvCert->id, + &rvCert->encoding, + &rvCert->issuer, + &rvCert->serial, + &rvCert->subject, + &rvCert->email); + if (status != PR_SUCCESS) { + return (NSSCertificate *)NULL; + } + return rvCert; +} + NSS_IMPLEMENT NSSCertificate * nssCertificate_AddRef ( @@ -74,7 +108,7 @@ nssCertificate_AddRef } NSS_IMPLEMENT PRStatus -NSSCertificate_Destroy +nssCertificate_Destroy ( NSSCertificate *c ) @@ -92,37 +126,84 @@ NSSCertificate_Destroy return PR_SUCCESS; } +NSS_IMPLEMENT PRStatus +NSSCertificate_Destroy +( + NSSCertificate *c +) +{ + return nssCertificate_Destroy(c); +} + +NSS_IMPLEMENT NSSDER * +nssCertificate_GetEncoding +( + NSSCertificate *c +) +{ + if (c->encoding.size > 0 && c->encoding.data) { + return &c->encoding; + } else { + return (NSSDER *)NULL; + } +} + +NSS_IMPLEMENT NSSDER * +nssCertificate_GetIssuer +( + NSSCertificate *c +) +{ + if (c->issuer.size > 0 && c->issuer.data) { + return &c->issuer; + } else { + return (NSSDER *)NULL; + } +} + +NSS_IMPLEMENT NSSDER * +nssCertificate_GetSerialNumber +( + NSSCertificate *c +) +{ + if (c->serial.size > 0 && c->serial.data) { + return &c->serial; + } else { + return (NSSDER *)NULL; + } +} + +NSS_IMPLEMENT NSSDER * +nssCertificate_GetSubject +( + NSSCertificate *c +) +{ + if (c->subject.size > 0 && c->subject.data) { + return &c->subject; + } else { + return (NSSDER *)NULL; + } +} + NSS_IMPLEMENT NSSUTF8 * -NSSCertificate_GetNickname +nssCertificate_GetNickname ( NSSCertificate *c, NSSToken *tokenOpt ) { - NSSUTF8 *rvNick = NULL; - nssCryptokiInstance *instance; - nssListIterator *instances = c->object.instances; - if (c->object.cryptoContext) { - return c->object.tempName; - } - for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); - instance != (nssCryptokiInstance *)NULL; - instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { - if (tokenOpt) { - if (instance->token == tokenOpt) { - /* take the nickname on the given token */ - rvNick = instance->label; - break; - } - } else { - /* take the first one */ - rvNick = instance->label; - break; - } - } - nssListIterator_Finish(instances); - return rvNick; + return nssPKIObject_GetNicknameForToken(&c->object, tokenOpt); +} + +NSS_IMPLEMENT NSSASCII7 * +nssCertificate_GetEmailAddress +( + NSSCertificate *c +) +{ + return c->email; } NSS_IMPLEMENT PRStatus @@ -132,39 +213,7 @@ NSSCertificate_DeleteStoredObject NSSCallback *uhh ) { - /* this needs more thought on what will happen when there are multiple - * instances - */ - /* XXX use callback to log in if neccessary */ - PRStatus nssrv = PR_SUCCESS; - nssCryptokiInstance *instance; - nssListIterator *instances = c->object.instances; - for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); - instance != (nssCryptokiInstance *)NULL; - instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { - /* XXX this should be fixed to understand read-only tokens, for - * now, to handle the builtins, just make the attempt. - */ - nssrv = nssToken_DeleteStoredObject(instance); - if (nssrv == PR_SUCCESS) { - nssList_Remove(c->object.instanceList, instance); -#ifdef NSS_3_4_CODE - if (instance->token->certList) { - /* If the cert has been cached locally on the token, remove - * that reference - */ - nssList_Remove(instance->token->certList, c); - NSSCertificate_Destroy(c); - } -#endif - } - } - nssListIterator_Finish(instances); - c->object.instances = nssList_CreateIterator(c->object.instanceList); - nssListIterator_Destroy(instances); - /* XXX for now, always success */ - return PR_SUCCESS; + return nssPKIObject_DeleteStoredObject(&c->object, uhh, PR_TRUE); } NSS_IMPLEMENT PRStatus @@ -238,79 +287,88 @@ nssCertificate_GetDecoding return c->decoding; } -static void -nssCertificateArray_Destroy +static NSSCertificate * +filter_subject_certs_for_id ( - NSSCertificate **certArray + NSSCertificate **subjectCerts, + NSSItem *id ) { - NSSCertificate **ci; - ci = certArray; - while (ci && *ci) { - NSSCertificate_Destroy(*ci); - ci++; - } - nss_ZFreeIf(certArray); -} - -static NSSCertificate * -filter_subject_certs_for_id(NSSCertificate **subjectCerts, NSSItem *id) -{ NSSCertificate **si; NSSCertificate *rvCert = NULL; nssDecodedCert *dcp; /* walk the subject certs */ - si = subjectCerts; - while (*si) { + for (si = subjectCerts; *si; si++) { dcp = nssCertificate_GetDecoding(*si); if (dcp->matchIdentifier(dcp, id)) { /* this cert has the correct identifier */ rvCert = nssCertificate_AddRef(*si); break; } - si++; } return rvCert; } static NSSCertificate * -find_issuer_cert_for_identifier(NSSCertificate *c, NSSItem *id) +find_cert_issuer +( + NSSCertificate *c, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt +) { - NSSCertificate *rvCert = NULL; - NSSCertificate **subjectCerts = NULL; + NSSArena *arena; + NSSCertificate **certs = NULL; + NSSCertificate **ccIssuers = NULL; + NSSCertificate **tdIssuers = NULL; + NSSCertificate *issuer = NULL; NSSTrustDomain *td; NSSCryptoContext *cc; - /* Find all certs with this cert's issuer as the subject */ cc = c->object.cryptoContext; /* NSSCertificate_GetCryptoContext(c); */ + td = NSSCertificate_GetTrustDomain(c); +#ifdef NSS_3_4_CODE + if (!td) { + td = STAN_GetDefaultTrustDomain(); + } +#endif + arena = nssArena_Create(); + if (!arena) { + return (NSSCertificate *)NULL; + } if (cc) { - subjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc, - &c->issuer, - NULL, - 0, - NULL); - if (subjectCerts) { - rvCert = filter_subject_certs_for_id(subjectCerts, id); - nssCertificateArray_Destroy(subjectCerts); - } + ccIssuers = nssCryptoContext_FindCertificatesBySubject(cc, + &c->issuer, + NULL, + 0, + arena); } - if (!rvCert) { - /* The general behavior of NSS <3.4 seems to be that if the search - * turns up empty in the temp db, fall back to the perm db, - * irregardless of whether or not the cert itself is perm or temp. - * This is replicated here. - */ - td = NSSCertificate_GetTrustDomain(c); - subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, - &c->issuer, - NULL, - 0, - NULL); - if (subjectCerts) { - rvCert = filter_subject_certs_for_id(subjectCerts, id); - nssCertificateArray_Destroy(subjectCerts); + tdIssuers = nssTrustDomain_FindCertificatesBySubject(td, + &c->issuer, + NULL, + 0, + arena); + certs = nssCertificateArray_Join(ccIssuers, tdIssuers); + if (certs) { + nssDecodedCert *dc = NULL; + NSSItem *issuerID = NULL; + dc = nssCertificate_GetDecoding(c); + if (dc) { + issuerID = dc->getIssuerIdentifier(dc); } + if (issuerID) { + issuer = filter_subject_certs_for_id(certs, issuerID); + nssItem_Destroy(issuerID); + } else { + issuer = nssCertificateArray_FindBestCertificate(certs, + timeOpt, + usage, + policiesOpt); + } + nssCertificateArray_Destroy(certs); } - return rvCert; + nssArena_Destroy(arena); + return issuer; } /* XXX review based on CERT_FindCertIssuer @@ -318,145 +376,110 @@ find_issuer_cert_for_identifier(NSSCertificate *c, NSSItem *id) * if authority key id does not exist */ NSS_IMPLEMENT NSSCertificate ** -NSSCertificate_BuildChain +nssCertificate_BuildChain ( NSSCertificate *c, NSSTime *timeOpt, NSSUsage *usage, NSSPolicies *policiesOpt, NSSCertificate **rvOpt, - PRUint32 rvLimit, /* zero for no limit */ + PRUint32 rvLimit, NSSArena *arenaOpt, PRStatus *statusOpt ) { - PRStatus nssrv; - nssList *chain; - NSSItem *issuerID; + PRStatus status; NSSCertificate **rvChain; +#ifdef NSS_3_4_CODE + NSSCertificate *cp; +#endif NSSTrustDomain *td; - NSSCryptoContext *cc; - nssDecodedCert *dc; - NSSCertificate *ct, *cp; - cc = c->object.cryptoContext; /* NSSCertificate_GetCryptoContext(c); */ + nssPKIObjectCollection *collection; td = NSSCertificate_GetTrustDomain(c); #ifdef NSS_3_4_CODE if (!td) { td = STAN_GetDefaultTrustDomain(); } #endif - chain = nssList_Create(NULL, PR_FALSE); - nssList_Add(chain, nssCertificate_AddRef(c)); if (statusOpt) *statusOpt = PR_SUCCESS; - if (rvLimit == 1) goto finish; - while (!nssItem_Equal(&c->subject, &c->issuer, &nssrv)) { - dc = nssCertificate_GetDecoding(c); - issuerID = dc->getIssuerIdentifier(dc); - if (issuerID) { - c = find_issuer_cert_for_identifier(c, issuerID); - nssItem_Destroy(issuerID); - issuerID = NULL; - if (!c) { - nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); - if (statusOpt) *statusOpt = PR_FAILURE; - goto finish; - } - } else { - nssBestCertificateCB best; - NSSDER *issuer = &c->issuer; + collection = nssCertificateCollection_Create(td, NULL); + if (!collection) { + if (statusOpt) *statusOpt = PR_FAILURE; + return (NSSCertificate **)NULL; + } + nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); + if (rvLimit == 1) { + goto finish; + } + while (!nssItem_Equal(&c->subject, &c->issuer, &status)) { #ifdef NSS_3_4_CODE + cp = c; +#endif + c = find_cert_issuer(c, timeOpt, usage, policiesOpt); +#ifdef NSS_3_4_CODE + if (!c) { PRBool tmpca = usage->nss3lookingForCA; usage->nss3lookingForCA = PR_TRUE; -#endif - c = ct = cp = NULL; - if (cc) { - ct = NSSCryptoContext_FindBestCertificateBySubject(cc, - issuer, - timeOpt, - usage, - policiesOpt); - /* Mimic functionality from CERT_FindCertIssuer. If a matching - * cert (based on trust & usage) cannot be found, just take the - * newest cert with the correct subject. - */ - if (!ct && !usage->anyUsage) { - usage->anyUsage = PR_TRUE; - ct = NSSCryptoContext_FindBestCertificateBySubject(cc, - issuer, - timeOpt, - usage, - policiesOpt); - usage->anyUsage = PR_FALSE; - } - } - cp = NSSTrustDomain_FindBestCertificateBySubject(td, - issuer, - timeOpt, - usage, - policiesOpt); - /* Mimic functionality from CERT_FindCertIssuer. If a matching - * cert (based on trust & usage) cannot be found, just take the - * newest cert with the correct subject. - */ - if (!cp && !usage->anyUsage) { + c = find_cert_issuer(cp, timeOpt, usage, policiesOpt); + if (!c && !usage->anyUsage) { usage->anyUsage = PR_TRUE; - cp = NSSTrustDomain_FindBestCertificateBySubject(td, - issuer, - timeOpt, - usage, - policiesOpt); + c = find_cert_issuer(cp, timeOpt, usage, policiesOpt); usage->anyUsage = PR_FALSE; } - nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt); - /* Take the better of the best temp and best perm cert, according - * to the given usage - */ - if (ct) { - nssBestCertificate_Callback(ct, (void *)&best); - } - if (cp) { - nssBestCertificate_Callback(cp, (void *)&best); - } - if (!best.cert) { - best.usage->anyUsage = PR_TRUE; - /* Take the newest of the best temp and best perm cert */ - if (ct) { - nssBestCertificate_Callback(ct, (void *)&best); - } - if (cp) { - nssBestCertificate_Callback(cp, (void *)&best); - } - } - if (ct) NSSCertificate_Destroy(ct); - if (cp) NSSCertificate_Destroy(cp); - c = best.cert; -#ifdef NSS_3_4_CODE usage->nss3lookingForCA = tmpca; -#endif - if (!c) { - nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); - if (statusOpt) *statusOpt = PR_FAILURE; - goto finish; + } +#endif /* NSS_3_4_CODE */ + if (c) { + nssPKIObjectCollection_AddObject(collection, (nssPKIObject *)c); + nssCertificate_Destroy(c); /* collection has it */ + if (rvLimit > 0 && + nssPKIObjectCollection_Count(collection) == rvLimit) + { + break; } + } else { + nss_SetError(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND); + if (statusOpt) *statusOpt = PR_FAILURE; + break; } - nssList_Add(chain, c); - if (nssList_Count(chain) == rvLimit) goto finish; } finish: - if (rvOpt) { - rvChain = rvOpt; - } else { - rvLimit = nssList_Count(chain); - rvChain = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvLimit + 1); - } - nssList_GetArray(chain, (void **)rvChain, rvLimit); - nssList_Destroy(chain); - /* XXX now, the question is, cache all certs in the chain? */ + rvChain = nssPKIObjectCollection_GetCertificates(collection, + rvOpt, + rvLimit, + arenaOpt); + nssPKIObjectCollection_Destroy(collection); return rvChain; } +NSS_IMPLEMENT NSSCertificate ** +NSSCertificate_BuildChain +( + NSSCertificate *c, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt, + NSSCertificate **rvOpt, + PRUint32 rvLimit, /* zero for no limit */ + NSSArena *arenaOpt, + PRStatus *statusOpt +) +{ + return nssCertificate_BuildChain(c, timeOpt, usage, policiesOpt, + rvOpt, rvLimit, arenaOpt, statusOpt); +} + +NSS_IMPLEMENT NSSCryptoContext * +nssCertificate_GetCryptoContext +( + NSSCertificate *c +) +{ + return c->object.cryptoContext; +} + NSS_IMPLEMENT NSSTrustDomain * -NSSCertificate_GetTrustDomain +nssCertificate_GetTrustDomain ( NSSCertificate *c ) @@ -464,6 +487,15 @@ NSSCertificate_GetTrustDomain return c->object.trustDomain; } +NSS_IMPLEMENT NSSTrustDomain * +NSSCertificate_GetTrustDomain +( + NSSCertificate *c +) +{ + return nssCertificate_GetTrustDomain(c); +} + NSS_IMPLEMENT NSSToken * NSSCertificate_GetToken ( @@ -782,7 +814,9 @@ nssBestCertificate_Callback * what the trust values are for the cert. * Ignore the returned pointer, the refcount is in c anyway. */ - (void)STAN_GetCERTCertificate(c); + if (STAN_GetCERTCertificate(c) == NULL) { + return PR_FAILURE; + } #endif if (dc->matchUsage(dc, best->usage)) { best->cert = nssCertificate_AddRef(c); @@ -825,22 +859,24 @@ nssSMIMEProfile_Create NSSItem *profileData ) { - PRStatus nssrv; NSSArena *arena; nssSMIMEProfile *rvProfile; + nssPKIObject *object; + NSSTrustDomain *td = nssCertificate_GetTrustDomain(cert); + NSSCryptoContext *cc = nssCertificate_GetCryptoContext(cert); arena = nssArena_Create(); if (!arena) { return NULL; } + object = nssPKIObject_Create(arena, NULL, td, cc); + if (!object) { + goto loser; + } rvProfile = nss_ZNEW(arena, nssSMIMEProfile); if (!rvProfile) { - nssArena_Destroy(arena); - return NULL; - } - nssrv = nssPKIObject_Initialize(&rvProfile->object, arena, NULL, NULL); - if (nssrv != PR_SUCCESS) { goto loser; } + rvProfile->object = *object; rvProfile->certificate = cert; rvProfile->email = nssUTF8_Duplicate(cert->email, arena); rvProfile->subject = nssItem_Duplicate(&cert->subject, arena, NULL); @@ -852,8 +888,8 @@ nssSMIMEProfile_Create } return rvProfile; loser: - nssPKIObject_Destroy(&rvProfile->object); - return NULL; + nssPKIObject_Destroy(object); + return (nssSMIMEProfile *)NULL; } /* execute a callback function on all members of a cert list */ @@ -896,6 +932,65 @@ nssCertificateList_AddReferences } NSS_IMPLEMENT NSSTrust * +nssTrust_Create +( + nssPKIObject *object +) +{ + PRStatus status; + PRUint32 i; + PRUint32 lastTrustOrder, myTrustOrder; + NSSTrust *rvt; + nssCryptokiObject *instance; + nssTrustLevel serverAuth, clientAuth, codeSigning, emailProtection; + lastTrustOrder = 1<<16; /* just make it big */ + PR_ASSERT(object->instances != NULL && object->numInstances > 0); + rvt = nss_ZNEW(object->arena, NSSTrust); + if (!rvt) { + return (NSSTrust *)NULL; + } + rvt->object = *object; + /* trust has to peek into the base object members */ + PZ_Lock(object->lock); + for (i=0; i<object->numInstances; i++) { + instance = object->instances[i]; + myTrustOrder = nssToken_GetTrustOrder(instance->token); + status = nssCryptokiTrust_GetAttributes(instance, NULL, + &serverAuth, + &clientAuth, + &codeSigning, + &emailProtection); + if (status != PR_SUCCESS) { + PZ_Unlock(object->lock); + return (NSSTrust *)NULL; + } + if (rvt->serverAuth == nssTrustLevel_Unknown || + myTrustOrder < lastTrustOrder) + { + rvt->serverAuth = serverAuth; + } + if (rvt->clientAuth == nssTrustLevel_Unknown || + myTrustOrder < lastTrustOrder) + { + rvt->clientAuth = clientAuth; + } + if (rvt->emailProtection == nssTrustLevel_Unknown || + myTrustOrder < lastTrustOrder) + { + rvt->emailProtection = emailProtection; + } + if (rvt->codeSigning == nssTrustLevel_Unknown || + myTrustOrder < lastTrustOrder) + { + rvt->codeSigning = codeSigning; + } + lastTrustOrder = myTrustOrder; + } + PZ_Unlock(object->lock); + return rvt; +} + +NSS_IMPLEMENT NSSTrust * nssTrust_AddRef ( NSSTrust *trust @@ -943,3 +1038,78 @@ nssSMIMEProfile_Destroy return PR_SUCCESS; } +NSS_IMPLEMENT NSSCRL * +nssCRL_Create +( + nssPKIObject *object +) +{ + PRStatus status; + NSSCRL *rvCRL; + NSSArena *arena = object->arena; + PR_ASSERT(object->instances != NULL && object->numInstances > 0); + rvCRL = nss_ZNEW(arena, NSSCRL); + if (!rvCRL) { + return (NSSCRL *)NULL; + } + rvCRL->object = *object; + /* XXX should choose instance based on some criteria */ + status = nssCryptokiCRL_GetAttributes(object->instances[0], + NULL, /* XXX sessionOpt */ + arena, + &rvCRL->encoding, + &rvCRL->url, + &rvCRL->isKRL); + if (status != PR_SUCCESS) { + return (NSSCRL *)NULL; + } + return rvCRL; +} + +NSS_IMPLEMENT NSSCRL * +nssCRL_AddRef +( + NSSCRL *crl +) +{ + if (crl) { + nssPKIObject_AddRef(&crl->object); + } + return crl; +} + +NSS_IMPLEMENT PRStatus +nssCRL_Destroy +( + NSSCRL *crl +) +{ + if (crl) { + (void)nssPKIObject_Destroy(&crl->object); + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssCRL_DeleteStoredObject +( + NSSCRL *crl, + NSSCallback *uhh +) +{ + return nssPKIObject_DeleteStoredObject(&crl->object, uhh, PR_TRUE); +} + +NSS_IMPLEMENT NSSDER * +nssCRL_GetEncoding +( + NSSCRL *crl +) +{ + if (crl->encoding.data != NULL && crl->encoding.size > 0) { + return &crl->encoding; + } else { + return (NSSDER *)NULL; + } +} + diff --git a/security/nss/lib/pki/config.mk b/security/nss/lib/pki/config.mk index 9614977ee..4a9ed7dda 100644 --- a/security/nss/lib/pki/config.mk +++ b/security/nss/lib/pki/config.mk @@ -1,4 +1,4 @@ -# +# # 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 @@ -30,115 +30,19 @@ # may use your version of this file under either the MPL or the # GPL. # - -#CONFIG_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$ $Name$" +CONFIG_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$ $Name$" ifdef BUILD_IDG DEFINES += -DNSSDEBUG endif -# can't do this in manifest.mn because OS_TARGET isn't defined there. -ifeq (,$(filter-out WIN%,$(OS_TARGET))) - -# don't want the 32 in the shared library name -SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll -IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib - -DLLFLAGS += -DEF:nsspki.def -RES = $(OBJDIR)/nsspki.res -RESNAME = nsspki.rc - -# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) - -SHARED_LIBRARY_LIBS = \ - $(DIST)/lib/nssb.lib \ - $(DIST)/lib/nssdev.lib \ - $(DIST)/lib/nsspki.lib \ - $(NULL) - -SHARED_LIBRARY_DIRS = \ - ../base \ - ../dev \ - $(NULL) - -EXTRA_LIBS += \ - $(NULL) - -EXTRA_SHARED_LIBS += \ - $(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) -SHARED_LIBRARY_LIBS = \ - $(DIST)/lib/libnssb.$(LIB_SUFFIX) \ - $(DIST)/lib/libnssdev.$(LIB_SUFFIX) \ - $(DIST)/lib/libnsspki.$(LIB_SUFFIX) \ - $(NULL) - -EXTRA_LIBS += \ - $(NULL) - -SHARED_LIBRARY_DIRS = \ - ../base \ - ../dev \ - $(NULL) - -# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) -# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. -EXTRA_SHARED_LIBS += \ - -L$(DIST)/lib/ \ - -lplc4 \ - -lplds4 \ - -lnspr4 \ - $(NULL) -endif - -ifeq ($(OS_TARGET),SunOS) -MAPFILE = $(OBJDIR)/nsspkimap.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_TARGET),AIX) -MAPFILE = $(OBJDIR)/nsspkimap.aix -ALL_TRASH += $(MAPFILE) -EXPORT_RULES = -bexport:$(MAPFILE) -endif - -ifeq ($(OS_TARGET),HP-UX) -MAPFILE = $(OBJDIR)/nsspkimap.hp -ALL_TRASH += $(MAPFILE) -MKSHLIB += -c $(MAPFILE) -endif - -ifeq ($(OS_TARGET), OSF1) -MAPFILE = $(OBJDIR)/nsspkimap.osf -ALL_TRASH += $(MAPFILE) -MKSHLIB += -hidden -input $(MAPFILE) -endif - -ifeq ($(OS_TARGET),Linux) -MAPFILE = $(OBJDIR)/nsspkimap.linux -ALL_TRASH += $(MAPFILE) -MKSHLIB += -Wl,--version-script,$(MAPFILE) -endif - +# +# Override TARGETS variable so that only static libraries +# are specifed as dependencies within rules.mk. +# - +TARGETS = $(LIBRARY) +SHARED_LIBRARY = +IMPORT_LIBRARY = +PROGRAM = diff --git a/security/nss/lib/pki/config34.mk b/security/nss/lib/pki/config34.mk deleted file mode 100644 index 4a9ed7dda..000000000 --- a/security/nss/lib/pki/config34.mk +++ /dev/null @@ -1,48 +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. -# -CONFIG_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$ $Name$" - -ifdef BUILD_IDG -DEFINES += -DNSSDEBUG -endif - -# -# Override TARGETS variable so that only static libraries -# are specifed as dependencies within rules.mk. -# - -TARGETS = $(LIBRARY) -SHARED_LIBRARY = -IMPORT_LIBRARY = -PROGRAM = - diff --git a/security/nss/lib/pki/cryptocontext.c b/security/nss/lib/pki/cryptocontext.c index f713bcb10..21d524072 100644 --- a/security/nss/lib/pki/cryptocontext.c +++ b/security/nss/lib/pki/cryptocontext.c @@ -35,33 +35,56 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef NSSPKI_H -#include "nsspki.h" -#endif /* NSSPKI_H */ +#ifndef DEV_H +#include "dev.h" +#endif /* DEV_H */ #ifndef PKIM_H #include "pkim.h" #endif /* PKIM_H */ -#ifndef PKIT_H -#include "pkit.h" -#endif /* PKIT_H */ - -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ - #ifndef PKISTORE_H #include "pkistore.h" #endif /* PKISTORE_H */ -#ifdef NSS_3_4_CODE -#include "pk11func.h" -#include "dev3hack.h" +#include "pki1t.h" + +#ifdef PURE_STAN_BUILD +struct NSSCryptoContextStr +{ + PRInt32 refCount; + NSSArena *arena; + NSSTrustDomain *td; + NSSToken *token; + nssSession *session; + nssCertificateStore *certStore; +}; #endif extern const NSSError NSS_ERROR_NOT_FOUND; +NSS_IMPLEMENT NSSCryptoContext * +nssCryptoContext_Create +( + NSSTrustDomain *td, + NSSCallback *uhhOpt +) +{ + NSSArena *arena; + NSSCryptoContext *rvCC; + arena = NSSArena_Create(); + if (!arena) { + return NULL; + } + rvCC = nss_ZNEW(arena, NSSCryptoContext); + if (!rvCC) { + return NULL; + } + rvCC->td = td; + rvCC->arena = arena; + return rvCC; +} + NSS_IMPLEMENT PRStatus NSSCryptoContext_Destroy ( @@ -177,9 +200,11 @@ nssCryptoContext_ImportTrust } } nssrv = nssCertificateStore_AddTrust(cc->certStore, trust); +#if 0 if (nssrv == PR_SUCCESS) { trust->object.cryptoContext = cc; } +#endif return nssrv; } @@ -198,9 +223,11 @@ nssCryptoContext_ImportSMIMEProfile } } nssrv = nssCertificateStore_AddSMIMEProfile(cc->certStore, profile); +#if 0 if (nssrv == PR_SUCCESS) { profile->object.cryptoContext = cc; } +#endif return nssrv; } @@ -214,36 +241,22 @@ NSSCryptoContext_FindBestCertificateByNickname NSSPolicies *policiesOpt /* NULL for none */ ) { - PRIntn i; - NSSCertificate *c; - NSSCertificate **nickCerts; - nssBestCertificateCB best; + NSSCertificate **certs; + NSSCertificate *rvCert = NULL; if (!cc->certStore) { return NULL; } - nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt); - /* This could be improved by querying the store with a callback */ - nickCerts = nssCertificateStore_FindCertificatesByNickname(cc->certStore, - name, - NULL, - 0, - NULL); - if (nickCerts) { - PRStatus nssrv; - for (i=0, c = *nickCerts; c != NULL; c = nickCerts[++i]) { - nssrv = nssBestCertificate_Callback(c, &best); - NSSCertificate_Destroy(c); - if (nssrv != PR_SUCCESS) { - if (best.cert) { - NSSCertificate_Destroy(best.cert); - best.cert = NULL; - } - break; - } - } - nss_ZFreeIf(nickCerts); + certs = nssCertificateStore_FindCertificatesByNickname(cc->certStore, + name, + NULL, 0, NULL); + if (certs) { + rvCert = nssCertificateArray_FindBestCertificate(certs, + timeOpt, + usage, + policiesOpt); + nssCertificateArray_Destroy(certs); } - return best.cert; + return rvCert; } NSS_IMPLEMENT NSSCertificate ** @@ -295,39 +308,26 @@ NSSCryptoContext_FindBestCertificateBySubject NSSPolicies *policiesOpt ) { - PRIntn i; - NSSCertificate *c; - NSSCertificate **subjectCerts; - nssBestCertificateCB best; + NSSCertificate **certs; + NSSCertificate *rvCert = NULL; if (!cc->certStore) { return NULL; } - nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt); - subjectCerts = nssCertificateStore_FindCertificatesBySubject(cc->certStore, - subject, - NULL, - 0, - NULL); - if (subjectCerts) { - PRStatus nssrv; - for (i=0, c = *subjectCerts; c != NULL; c = subjectCerts[++i]) { - nssrv = nssBestCertificate_Callback(c, &best); - NSSCertificate_Destroy(c); - if (nssrv != PR_SUCCESS) { - if (best.cert) { - NSSCertificate_Destroy(best.cert); - best.cert = NULL; - } - break; - } - } - nss_ZFreeIf(subjectCerts); + certs = nssCertificateStore_FindCertificatesBySubject(cc->certStore, + subject, + NULL, 0, NULL); + if (certs) { + rvCert = nssCertificateArray_FindBestCertificate(certs, + timeOpt, + usage, + policiesOpt); + nssCertificateArray_Destroy(certs); } - return best.cert; + return rvCert; } NSS_IMPLEMENT NSSCertificate ** -NSSCryptoContext_FindCertificatesBySubject +nssCryptoContext_FindCertificatesBySubject ( NSSCryptoContext *cc, NSSDER *subject, @@ -348,6 +348,21 @@ NSSCryptoContext_FindCertificatesBySubject return rvCerts; } +NSS_IMPLEMENT NSSCertificate ** +NSSCryptoContext_FindCertificatesBySubject +( + NSSCryptoContext *cc, + NSSDER *subject, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt +) +{ + return nssCryptoContext_FindCertificatesBySubject(cc, subject, + rvOpt, maximumOpt, + arenaOpt); +} + NSS_IMPLEMENT NSSCertificate * NSSCryptoContext_FindBestCertificateByNameComponents ( @@ -401,35 +416,22 @@ NSSCryptoContext_FindBestCertificateByEmail NSSPolicies *policiesOpt ) { - PRIntn i; - NSSCertificate *c; - NSSCertificate **emailCerts; - nssBestCertificateCB best; + NSSCertificate **certs; + NSSCertificate *rvCert = NULL; if (!cc->certStore) { return NULL; } - nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt); - emailCerts = nssCertificateStore_FindCertificatesByEmail(cc->certStore, - email, - NULL, - 0, - NULL); - if (emailCerts) { - PRStatus nssrv; - for (i=0, c = *emailCerts; c != NULL; c = emailCerts[++i]) { - nssrv = nssBestCertificate_Callback(c, &best); - NSSCertificate_Destroy(c); - if (nssrv != PR_SUCCESS) { - if (best.cert) { - NSSCertificate_Destroy(best.cert); - best.cert = NULL; - } - break; - } - } - nss_ZFreeIf(emailCerts); + certs = nssCertificateStore_FindCertificatesByEmail(cc->certStore, + email, + NULL, 0, NULL); + if (certs) { + rvCert = nssCertificateArray_FindBestCertificate(certs, + timeOpt, + usage, + policiesOpt); + nssCertificateArray_Destroy(certs); } - return best.cert; + return rvCert; } NSS_IMPLEMENT NSSCertificate ** @@ -649,31 +651,6 @@ struct token_session_str { nssSession *session; }; -#ifdef nodef -static nssSession * -get_token_session(NSSCryptoContext *cc, NSSToken *tok) -{ - struct token_session_str *ts; - for (ts = (struct token_session_str *)nssListIterator_Start(cc->sessions); - ts != (struct token_session_str *)NULL; - ts = (struct token_session_str *)nssListIterator_Next(cc->sessions)) - { - if (ts->token == tok) { /* will this need to be more general? */ - break; - } - } - nssListIterator_Finish(cc->sessions); - if (!ts) { - /* need to create a session for this token. */ - ts = nss_ZNEW(NULL, struct token_session_str); - ts->token = nssToken_AddRef(tok); - ts->session = nssSlot_CreateSession(tok->slot, cc->arena, PR_FALSE); - nssList_AddElement(cc->sessionList, (void *)ts); - } - return ts->session; -} -#endif - NSS_IMPLEMENT NSSItem * NSSCryptoContext_Decrypt ( @@ -685,58 +662,7 @@ NSSCryptoContext_Decrypt NSSArena *arenaOpt ) { -#if 0 - NSSToken *tok; - nssSession *session; - NSSItem *rvData; - PRUint32 dataLen; - NSSAlgorithmAndParameters *ap; - CK_RV ckrv; - ap = (apOpt) ? apOpt : cc->defaultAlgorithm; - /* Get the token for this operation */ - tok = nssTrustDomain_GetCryptoToken(cc->trustDomain, ap); - if (!tok) { - return (NSSItem *)NULL; - } - /* Get the local session for this token */ - session = get_token_session(cc, tok); - /* Get the key needed to decrypt */ - keyHandle = get_decrypt_key(cc, ap); - /* Set up the decrypt operation */ - ckrv = CKAPI(tok)->C_DecryptInit(session->handle, - &ap->mechanism, keyHandle); - if (ckrv != CKR_OK) { - /* handle PKCS#11 error */ - return (NSSItem *)NULL; - } - /* Get the length of the output buffer */ - ckrv = CKAPI(tok)->C_Decrypt(session->handle, - (CK_BYTE_PTR)encryptedData->data, - (CK_ULONG)encryptedData->size, - (CK_BYTE_PTR)NULL, - (CK_ULONG_PTR)&dataLen); - if (ckrv != CKR_OK) { - /* handle PKCS#11 error */ - return (NSSItem *)NULL; - } - /* Alloc return value memory */ - rvData = nssItem_Create(NULL, NULL, dataLen, NULL); - if (!rvItem) { - return (NSSItem *)NULL; - } - /* Do the decryption */ - ckrv = CKAPI(tok)->C_Decrypt(cc->session->handle, - (CK_BYTE_PTR)encryptedData->data, - (CK_ULONG)encryptedData->size, - (CK_BYTE_PTR)rvData->data, - (CK_ULONG_PTR)&dataLen); - if (ckrv != CKR_OK) { - /* handle PKCS#11 error */ - nssItem_ZFreeIf(rvData); - return (NSSItem *)NULL; - } - return rvData; -#endif + nss_SetError(NSS_ERROR_NOT_FOUND); return NULL; } diff --git a/security/nss/lib/pki/manifest.mn b/security/nss/lib/pki/manifest.mn index 2367cf8e4..c4bf70b24 100644 --- a/security/nss/lib/pki/manifest.mn +++ b/security/nss/lib/pki/manifest.mn @@ -55,6 +55,7 @@ CSRCS = \ tdcache.c \ certdecode.c \ pkistore.c \ + pkibase.c \ $(NULL) ifndef PURE_STAN_BUILD diff --git a/security/nss/lib/pki/nsspki.def b/security/nss/lib/pki/nsspki.def deleted file mode 100644 index d32a4d1e6..000000000 --- a/security/nss/lib/pki/nsspki.def +++ /dev/null @@ -1,249 +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) 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. -;+# -;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS -;+# 1. For all unix platforms, the string ";-" means "remove this line" -;+# 2. For all unix platforms, the string " DATA " will be removed from any -;+# line on which it occurs. -;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. -;+# On AIX, lines containing ";+" will be removed. -;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. -;+# 5. For all unix platforms, after the above processing has taken place, -;+# all characters after the first ";" on the line will be removed. -;+# And for AIX, the first ";" will also be removed. -;+# This file is passed directly to windows. Since ';' is a comment, all UNIX -;+# directives are hidden behind ";", ";+", and ";-" -;+# -;+# -;+# This file contains the complete Stan API to date. Functions that are -;+# not yet implemented are commented out. -;+ -;+NSS_3.4 { # NSS 3.4 release -;+ global: -LIBRARY nsspki3 ;- -EXPORTS ;- -NSSArena_Create -NSSArena_Destroy -NSS_GetError -NSS_GetErrorStack -;NSSCertificate_Destroy; -;NSSCertificate_DeleteStoredObject; -;NSSCertificate_Validate; -;NSSCertificate_ValidateCompletely; -;NSSCertificate_ValidateAndDiscoverUsagesAndPolicies; -;NSSCertificate_Encode; -;NSSCertificate_BuildChain; -;NSSCertificate_GetTrustDomain; -;NSSCertificate_GetToken; -;NSSCertificate_GetSlot; -;NSSCertificate_GetModule; -;NSSCertificate_Encrypt; -;NSSCertificate_Verify; -;NSSCertificate_VerifyRecover; -;NSSCertificate_WrapSymmetricKey; -;NSSCertificate_CreateCryptoContext; -;NSSCertificate_GetPublicKey; -;NSSCertificate_FindPrivateKey; -;NSSCertificate_IsPrivateKeyAvailable; -;NSSUserCertificate_IsStillPresent; -;NSSUserCertificate_Decrypt; -;NSSUserCertificate_Sign; -;NSSUserCertificate_SignRecover; -;NSSUserCertificate_UnwrapSymmetricKey; -;NSSUserCertificate_DeriveSymmetricKey; -;NSSPrivateKey_Destroy; -;NSSPrivateKey_DeleteStoredObject; -;NSSPrivateKey_GetSignatureLength; -;NSSPrivateKey_GetPrivateModulusLength; -;NSSPrivateKey_IsStillPresent; -;NSSPrivateKey_Encode; -;NSSPrivateKey_GetTrustDomain; -;NSSPrivateKey_GetToken; -;NSSPrivateKey_GetSlot; -;NSSPrivateKey_GetModule; -;NSSPrivateKey_Decrypt; -;NSSPrivateKey_Sign; -;NSSPrivateKey_SignRecover; -;NSSPrivateKey_UnwrapSymmetricKey; -;NSSPrivateKey_DeriveSymmetricKey; -;NSSPrivateKey_FindPublicKey; -;NSSPrivateKey_CreateCryptoContext; -;NSSPrivateKey_FindCertificates; -;NSSPrivateKey_FindBestCertificate; -;NSSPublicKey_Destroy; -;NSSPublicKey_DeleteStoredObject; -;NSSPublicKey_Encode; -;NSSPublicKey_GetTrustDomain; -;NSSPublicKey_GetToken; -;NSSPublicKey_GetSlot; -;NSSPublicKey_GetModule; -;NSSPublicKey_Encrypt; -;NSSPublicKey_Verify; -;NSSPublicKey_VerifyRecover; -;NSSPublicKey_WrapSymmetricKey; -;NSSPublicKey_CreateCryptoContext; -;NSSPublicKey_FindCertificates; -;NSSPublicKey_FindBestCertificate; -;NSSPublicKey_FindPrivateKey; -;NSSSymmetricKey_Destroy; -;NSSSymmetricKey_DeleteStoredObject; -;NSSSymmetricKey_GetKeyLength; -;NSSSymmetricKey_GetKeyStrength; -;NSSSymmetricKey_IsStillPresent; -;NSSSymmetricKey_GetTrustDomain; -;NSSSymmetricKey_GetToken; -;NSSSymmetricKey_GetSlot; -;NSSSymmetricKey_GetModule; -;NSSSymmetricKey_Encrypt; -;NSSSymmetricKey_Decrypt; -;NSSSymmetricKey_Sign; -;NSSSymmetricKey_SignRecover; -;NSSSymmetricKey_Verify; -;NSSSymmetricKey_VerifyRecover; -;NSSSymmetricKey_WrapSymmetricKey; -;NSSSymmetricKey_WrapPrivateKey; -;NSSSymmetricKey_UnwrapSymmetricKey; -;NSSSymmetricKey_UnwrapPrivateKey; -;NSSSymmetricKey_DeriveSymmetricKey; -;NSSSymmetricKey_CreateCryptoContext; -NSSTrustDomain_Create; -;NSSTrustDomain_Destroy; -;NSSTrustDomain_SetDefaultCallback; -;NSSTrustDomain_GetDefaultCallback; -NSSTrustDomain_LoadModule; -;NSSTrustDomain_DisableToken; -;NSSTrustDomain_EnableToken; -;NSSTrustDomain_IsTokenEnabled; -;NSSTrustDomain_FindSlotByName; -;NSSTrustDomain_FindTokenByName; -;NSSTrustDomain_FindTokenBySlotName; -;NSSTrustDomain_FindTokenForAlgorithm; -;NSSTrustDomain_FindBestTokenForAlgorithms; -;NSSTrustDomain_Login; -;NSSTrustDomain_Logout; -;NSSTrustDomain_ImportCertificate; -;NSSTrustDomain_ImportPKIXCertificate; -;NSSTrustDomain_ImportEncodedCertificate; -;NSSTrustDomain_ImportEncodedCertificateChain; -;NSSTrustDomain_ImportEncodedPrivateKey; -;NSSTrustDomain_ImportEncodedPublicKey; -;NSSTrustDomain_FindBestCertificateByNickname; -NSSTrustDomain_FindCertificatesByNickname -;NSSTrustDomain_FindCertificateByIssuerAndSerialNumber; -;NSSTrustDomain_FindBestCertificateBySubject; -;NSSTrustDomain_FindCertificatesBySubject; -;NSSTrustDomain_FindBestCertificateByNameComponents; -;NSSTrustDomain_FindCertificatesByNameComponents; -;NSSTrustDomain_FindCertificateByEncodedCertificate; -;NSSTrustDomain_FindCertificateByEmail; -;NSSTrustDomain_FindCertificatesByEmail; -;NSSTrustDomain_FindCertificateByOCSPHash; -;NSSTrustDomain_FindBestUserCertificate; -;NSSTrustDomain_FindUserCertificates; -;NSSTrustDomain_FindBestUserCertificateForSSLClientAuth; -;NSSTrustDomain_FindUserCertificatesForSSLClientAuth; -;NSSTrustDomain_FindBestUserCertificateForEmailSigning; -;NSSTrustDomain_FindUserCertificatesForEmailSigning; -;NSSTrustDomain_GenerateKeyPair; -;NSSTrustDomain_GenerateSymmetricKey; -;NSSTrustDomain_GenerateSymmetricKeyFromPassword; -;NSSTrustDomain_FindSymmetricKeyByAlgorithmAndKeyID; -;NSSTrustDomain_CreateCryptoContext; -;NSSTrustDomain_CreateCryptoContextForAlgorithm; -;NSSTrustDomain_CreateCryptoContextForAlgorithmAndParameters; -;NSSCryptoContext_Destroy; -;NSSCryptoContext_SetDefaultCallback; -;NSSCryptoContext_GetDefaultCallback; -;NSSCryptoContext_GetTrustDomain; -;NSSCryptoContext_ImportCertificate; -;NSSCryptoContext_ImportPKIXCertificate; -;NSSCryptoContext_ImportEncodedCertificate; -;NSSCryptoContext_ImportEncodedPKIXCertificateChain; -;NSSCryptoContext_FindBestCertificateByNickname; -;NSSCryptoContext_FindCertificatesByNickname; -;NSSCryptoContext_FindCertificateByIssuerAndSerialNumber; -;NSSCryptoContext_FindBestCertificateBySubject; -;NSSCryptoContext_FindCertificatesBySubject; -;NSSCryptoContext_FindBestCertificateByNameComponents; -;NSSCryptoContext_FindCertificatesByNameComponents; -;NSSCryptoContext_FindCertificateByEncodedCertificate; -;NSSCryptoContext_FindBestCertificateByEmail; -;NSSCryptoContext_FindCertificatesByEmail; -;NSSCryptoContext_FindCertificateByOCSPHash; -;NSSCryptoContext_FindBestUserCertificate; -;NSSCryptoContext_FindUserCertificates; -;NSSCryptoContext_FindBestUserCertificateForSSLClientAuth; -;NSSCryptoContext_FindUserCertificatesForSSLClientAuth; -;NSSCryptoContext_FindBestUserCertificateForEmailSigning; -;NSSCryptoContext_FindUserCertificatesForEmailSigning; -;NSSCryptoContext_GenerateKeyPair; -;NSSCryptoContext_GenerateSymmetricKey; -;NSSCryptoContext_GenerateSymmetricKeyFromPassword; -;NSSCryptoContext_FindSymmetricKeyByAlgorithmAndKeyID; -;NSSCryptoContext_Decrypt; -;NSSCryptoContext_BeginDecrypt; -;NSSCryptoContext_ContinueDecrypt; -;NSSCryptoContext_FinishDecrypt; -;NSSCryptoContext_Sign; -;NSSCryptoContext_BeginSign; -;NSSCryptoContext_ContinueSign; -;NSSCryptoContext_FinishSign; -;NSSCryptoContext_SignRecover; -;NSSCryptoContext_BeginSignRecover; -;NSSCryptoContext_ContinueSignRecover; -;NSSCryptoContext_FinishSignRecover; -;NSSCryptoContext_UnwrapSymmetricKey; -;NSSCryptoContext_DeriveSymmetricKey; -;NSSCryptoContext_Encrypt; -;NSSCryptoContext_BeginEncrypt; -;NSSCryptoContext_ContinueEncrypt; -;NSSCryptoContext_FinishEncrypt; -;NSSCryptoContext_Verify; -;NSSCryptoContext_BeginVerify; -;NSSCryptoContext_ContinueVerify; -;NSSCryptoContext_FinishVerify; -;NSSCryptoContext_VerifyRecover; -;NSSCryptoContext_BeginVerifyRecover; -;NSSCryptoContext_ContinueVerifyRecover; -;NSSCryptoContext_FinishVerifyRecover; -;NSSCryptoContext_WrapSymmetricKey; -;NSSCryptoContext_Digest; -;NSSCryptoContext_BeginDigest; -;NSSCryptoContext_ContinueDigest; -;NSSCryptoContext_FinishDigest; -;NSSCryptoContext_Clone; -;+ local: -NSSTrustDomain_TraverseCertificates; -NSSCertificate_GetID; -NSSCertificate_GetLabel; -;+ *; -;+}; diff --git a/security/nss/lib/pki/nsspki.rc b/security/nss/lib/pki/nsspki.rc deleted file mode 100644 index 5228cefb3..000000000 --- a/security/nss/lib/pki/nsspki.rc +++ /dev/null @@ -1,98 +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) 2001 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 "nss.h" -#include <winver.h> - -#define MY_LIBNAME "nsspki" -#define MY_FILEDESCRIPTION "NSS PKI Base Library" - -#define STRINGIZE(x) #x -#define STRINGIZE2(x) STRINGIZE(x) -#define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR) - -#ifdef _DEBUG -#define MY_DEBUG_STR " (debug)" -#define MY_FILEFLAGS_1 VS_FF_DEBUG -#else -#define MY_DEBUG_STR "" -#define MY_FILEFLAGS_1 0x0L -#endif -#if NSS_BETA -#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE -#else -#define MY_FILEFLAGS_2 MY_FILEFLAGS_1 -#endif - -#ifdef WINNT -#define MY_FILEOS VOS_NT_WINDOWS32 -#else -#define MY_FILEOS VOS__WINDOWS32 -#endif - -#define MY_INTERNAL_NAME MY_LIBNAME NSS_VMAJOR_STR - -///////////////////////////////////////////////////////////////////////////// -// -// Version-information resource -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0 - PRODUCTVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS MY_FILEFLAGS_2 - FILEOS MY_FILEOS - FILETYPE VFT_DLL - FILESUBTYPE 0x0L // not used - -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" // Lang=US English, CharSet=Unicode - BEGIN - VALUE "CompanyName", "Netscape Communications Corporation\0" - VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" - VALUE "FileVersion", NSS_VERSION "\0" - VALUE "InternalName", MY_INTERNAL_NAME "\0" - VALUE "LegalCopyright", "Copyright \251 1994-2001 Netscape Communications Corporation\0" - VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" - VALUE "ProductName", "Network Security Services\0" - VALUE "ProductVersion", NSS_VERSION "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/security/nss/lib/pki/pki.h b/security/nss/lib/pki/pki.h index 4460b52be..d9af582b0 100644 --- a/security/nss/lib/pki/pki.h +++ b/security/nss/lib/pki/pki.h @@ -38,29 +38,147 @@ static const char PKI_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef PKIT_H -#include "pkit.h" -#endif /* PKIT_H */ - #ifndef NSSDEVT_H #include "nssdevt.h" #endif /* NSSDEVT_H */ +#ifndef NSSPKI_H +#include "nsspki.h" +#endif /* NSSPKI_H */ + +#ifndef PKIT_H +#include "pkit.h" +#endif /* PKIT_H */ + PR_BEGIN_EXTERN_C +NSS_EXTERN NSSCallback * +nssTrustDomain_GetDefaultCallback +( + NSSTrustDomain *td, + PRStatus *statusOpt +); + +NSS_EXTERN NSSCertificate ** +nssTrustDomain_FindCertificatesBySubject +( + NSSTrustDomain *td, + NSSDER *subject, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSTrust * +nssTrustDomain_FindTrustForCertificate +( + NSSTrustDomain *td, + NSSCertificate *c +); + NSS_EXTERN NSSCertificate * nssCertificate_AddRef ( NSSCertificate *c ); +NSS_EXTERN PRStatus +nssCertificate_Destroy +( + NSSCertificate *c +); + +NSS_EXTERN NSSDER * +nssCertificate_GetEncoding +( + NSSCertificate *c +); + +NSS_EXTERN NSSDER * +nssCertificate_GetIssuer +( + NSSCertificate *c +); + +NSS_EXTERN NSSDER * +nssCertificate_GetSerialNumber +( + NSSCertificate *c +); + +NSS_EXTERN NSSDER * +nssCertificate_GetSubject +( + NSSCertificate *c +); + NSS_EXTERN NSSUTF8 * -NSSCertificate_GetNickname +nssCertificate_GetNickname ( NSSCertificate *c, NSSToken *tokenOpt ); +NSS_EXTERN NSSASCII7 * +nssCertificate_GetEmailAddress +( + NSSCertificate *c +); + +NSS_EXTERN PRBool +nssCertificate_IssuerAndSerialEqual +( + NSSCertificate *c1, + NSSCertificate *c2 +); + +NSS_EXTERN NSSPrivateKey * +nssPrivateKey_AddRef +( + NSSPrivateKey *vk +); + +NSS_EXTERN PRStatus +nssPrivateKey_Destroy +( + NSSPrivateKey *vk +); + +NSS_EXTERN NSSItem * +nssPrivateKey_GetID +( + NSSPrivateKey *vk +); + +NSS_EXTERN NSSUTF8 * +nssPrivateKey_GetNickname +( + NSSPrivateKey *vk, + NSSToken *tokenOpt +); + +NSS_EXTERN PRStatus +nssPublicKey_Destroy +( + NSSPublicKey *bk +); + +NSS_EXTERN NSSItem * +nssPublicKey_GetID +( + NSSPublicKey *vk +); + +NSS_EXTERN NSSCertificate ** +nssCryptoContext_FindCertificatesBySubject +( + NSSCryptoContext *cc, + NSSDER *subject, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt +); + /* putting here for now, needs more thought */ NSS_EXTERN PRStatus nssCryptoContext_ImportTrust diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c index 8a8d3bf63..93d840506 100644 --- a/security/nss/lib/pki/pki3hack.c +++ b/security/nss/lib/pki/pki3hack.c @@ -71,9 +71,6 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "pkistore.h" #include "secmod.h" -/* if it's got more than 10 certs, it better handle traversal well */ -#define NSSTOKEN_MAX_LOCAL_CERTS 10 - NSSTrustDomain *g_default_trust_domain = NULL; NSSCryptoContext *g_default_crypto_context = NULL; @@ -90,246 +87,6 @@ STAN_GetDefaultCryptoContext() return g_default_crypto_context; } -NSS_IMPLEMENT NSSToken * -STAN_GetDefaultCryptoToken -( - void -) -{ - PK11SlotInfo *pk11slot = PK11_GetInternalSlot(); - return PK11Slot_GetNSSToken(pk11slot); -} - -static CERTCertificate * -stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate); - -/* stuff the cert in the global trust domain cache, and then add a reference - * to remain with the token in a list. - */ -static PRStatus -cache_token_cert(NSSCertificate *c, void *arg) -{ - NSSToken *token = (NSSToken *)arg; - NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - NSSCertificate *cp = nssCertificate_AddRef(c); - if (nssList_Count(token->certList) > NSSTOKEN_MAX_LOCAL_CERTS) { - nssToken_DestroyCertList(token, PR_TRUE); - /* terminate the traversal */ - return PR_FAILURE; - } - nssTrustDomain_AddCertsToCache(td, &c, 1); - if (cp == c) { - NSSCertificate_Destroy(cp); - } else { - /* The cert was already in the cache, from another token. Add this - * token's instance to the cert. - */ - nssCryptokiInstance *tokenInstance, *instance; - nssList_GetArray(cp->object.instanceList, (void **)&tokenInstance, 1); - instance = nssCryptokiInstance_Create(c->object.arena, token, - tokenInstance->handle, PR_TRUE); - nssList_Add(c->object.instanceList, instance); - nssListIterator_Destroy(c->object.instances); - c->object.instances = nssList_CreateIterator(c->object.instanceList); - } - /* This list reference persists with the token */ - nssList_Add(token->certList, nssCertificate_AddRef(c)); - /* The cert needs to become external (made into a CERTCertificate) - * in order for it to be properly released. - * Force an update of the nickname and slot fields. - */ - (void)stan_GetCERTCertificate(c, PR_TRUE); - return PR_SUCCESS; -} - -static void remove_token_instance(NSSCertificate *c, NSSToken *token) -{ - nssListIterator *instances; - nssCryptokiInstance *instance, *rmInstance = NULL; - instances = c->object.instances; - for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); - instance != (nssCryptokiInstance *)NULL; - instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { - if (instance->token == token) { - rmInstance = instance; - break; - } - } - nssListIterator_Finish(instances); - if (rmInstance) { - nssList_Remove(c->object.instanceList, rmInstance); - nssListIterator_Destroy(instances); - c->object.instances = nssList_CreateIterator(c->object.instanceList); - } -} - -static PRBool instance_destructor(NSSCertificate *c, NSSToken *token) -{ - remove_token_instance(c, token); - if (nssList_Count(c->object.instanceList) == 0) { - return PR_TRUE; - } - return PR_FALSE; -} - -NSS_IMPLEMENT void -destroy_token_certs(nssList *certList, NSSToken *token, PRBool renewInstances) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRBool removeIt; - certs = nssList_CreateIterator(certList); - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - removeIt = instance_destructor(cert, token); - if (removeIt) { - nssList_Remove(certList, cert); - CERT_DestroyCertificate(STAN_GetCERTCertificate(cert)); - } else if (renewInstances) { - /* force an update of the nickname and slot fields of the cert */ - (void)stan_GetCERTCertificate(cert, PR_TRUE); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); -} - -NSS_IMPLEMENT void -nssCertificateList_DestroyTokenCerts(nssList *certList, NSSToken *token) -{ - destroy_token_certs(certList, token, PR_TRUE); -} - -NSS_IMPLEMENT void -nssCertificateList_RemoveTokenCerts(nssList *certList, NSSToken *token) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRBool removeIt; - certs = nssList_CreateIterator(certList); - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - removeIt = instance_destructor(cert, token); - if (removeIt) { - nssList_Remove(certList, cert); - } else { - /* force an update of the nickname and slot fields of the cert */ - (void)stan_GetCERTCertificate(cert, PR_TRUE); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); -} - -/* destroy the list of certs on a token */ -NSS_IMPLEMENT void -nssToken_DestroyCertList(NSSToken *token, PRBool renewInstances) -{ - if (!token->certList) { - return; - } - destroy_token_certs(token->certList, token, renewInstances); - nssList_Clear(token->certList, NULL); - /* leave the list non-null to prevent it from being searched */ -} - -/* create a list of local cert references for certain tokens */ -NSS_IMPLEMENT PRStatus -nssToken_LoadCerts(NSSToken *token) -{ - PRStatus nssrv = PR_SUCCESS; - nssTokenCertSearch search; - if (!PK11_IsInternal(token->pk11slot) && PK11_IsHW(token->pk11slot)) { - /* Hardware token certs will be immediately cached, and no searches - * will be performed on the token (the certs will be discovered by - * cache lookups) - */ - search.callback = cache_token_cert; - search.cbarg = token; - search.cached = NULL; - search.searchType = nssTokenSearchType_TokenOnly; - if (!token->certList) { - token->certList = nssList_Create(token->arena, PR_FALSE); - if (!token->certList) { - return PR_FAILURE; - } - } else if (nssList_Count(token->certList) > 0) { - /* already been done */ - return PR_SUCCESS; - } - /* ignore the rv, just work without the list */ - (void)nssToken_TraverseCertificates(token, NULL, &search); - (void)nssToken_SetTrustCache(token); - (void)nssToken_SetCrlCache(token); - - /* even if there are no certs, leave a valid list pointer should - * any be imported. Having the pointer will also prevent searches, - * see below. - */ - if (nssList_Count(token->certList) == 0 && - !PK11_IsLoggedIn(token->pk11slot, NULL)) { - /* If the token is not logged in, that may be the reason no - * certs were found. - */ - token->loggedIn = PR_FALSE; - } - } - return nssrv; -} - -NSS_IMPLEMENT void -nssToken_UpdateTrustForCerts(NSSToken *token) -{ - nssListIterator *certs; - NSSCertificate *cert; - certs = nssList_CreateIterator(token->certList); - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - CERTCertificate *cc = STAN_GetCERTCertificate(cert); - cc->trust = NULL; - /* force an update of the trust fields of the CERTCertificate */ - (void)stan_GetCERTCertificate(cert, PR_FALSE); - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); -} - -NSS_IMPLEMENT PRBool -nssToken_SearchCerts -( - NSSToken *token, - PRBool *notPresentOpt -) -{ - if (notPresentOpt) { - *notPresentOpt = PR_FALSE; - } - if (!nssToken_IsPresent(token)) { - nssToken_DestroyCertList(token, PR_TRUE); /* will free cached certs */ - if (notPresentOpt) { - *notPresentOpt = PR_TRUE; - } - } else if (token->certList && - nssList_Count(token->certList) == 0 && - !token->loggedIn) { - /* If the token has no cached certs, but wasn't logged in, check - * to see if it is logged in now and retry - */ - if (PK11_IsLoggedIn(token->pk11slot, NULL)) { - token->loggedIn = PR_TRUE; - nssToken_LoadCerts(token); - } - } - return (PRBool) (token->certList == NULL); -} - NSS_IMPLEMENT PRStatus STAN_LoadDefaultNSS3TrustDomain ( @@ -338,8 +95,6 @@ STAN_LoadDefaultNSS3TrustDomain { NSSTrustDomain *td; NSSToken *token; - PK11SlotList *list; - PK11SlotListElement *le; SECMODModuleList *mlp; SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); int i; @@ -358,17 +113,9 @@ STAN_LoadDefaultNSS3TrustDomain } } SECMOD_ReleaseReadLock(moduleLock); + td->tokens = nssList_CreateIterator(td->tokenList); g_default_trust_domain = td; g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL); - /* Cache hardware token certs with the token to make them persistent */ - td->tokens = nssList_CreateIterator(td->tokenList); - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - nssToken_LoadCerts(token); - } - nssListIterator_Finish(td->tokens); return PR_SUCCESS; } @@ -385,7 +132,6 @@ STAN_AddModuleToDefaultTrustDomain for (i=0; i<module->slotCount; i++) { token = nssToken_CreateFromPK11SlotInfo(td, module->slots[i]); PK11Slot_SetNSSToken(module->slots[i], token); - nssToken_LoadCerts(token); nssList_Add(td->tokenList, token); } nssListIterator_Destroy(td->tokens); @@ -393,15 +139,6 @@ STAN_AddModuleToDefaultTrustDomain return SECSuccess; } -NSS_IMPLEMENT void -STAN_DestroyNSSToken(NSSToken *token) -{ - if (token->certList) { - nssToken_DestroyCertList(token, PR_FALSE); - } - nssToken_Destroy(token); -} - NSS_IMPLEMENT SECStatus STAN_RemoveModuleFromDefaultTrustDomain ( @@ -416,7 +153,7 @@ STAN_RemoveModuleFromDefaultTrustDomain token = PK11Slot_GetNSSToken(module->slots[i]); if (token) { nssList_Remove(td->tokenList, token); - STAN_DestroyNSSToken(token); + nssToken_Destroy(token); } } nssListIterator_Destroy(td->tokens); @@ -461,6 +198,31 @@ STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der) return rvKey; } +NSS_IMPLEMENT PRStatus +nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der, NSSArena *arena, + NSSDER *issuer, NSSDER *serial) +{ + SECStatus secrv; + SECItem derCert; + SECItem derIssuer = { 0 }; + SECItem derSerial = { 0 }; + SECITEM_FROM_NSSITEM(&derCert, der); + secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial); + if (secrv != SECSuccess) { + return PR_FAILURE; + } + (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data); + secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer); + if (secrv != SECSuccess) { + PORT_Free(derSerial.data); + return PR_FAILURE; + } + (void)nssItem_Create(arena, issuer, derIssuer.len, derIssuer.data); + PORT_Free(derSerial.data); + PORT_Free(derIssuer.data); + return PR_SUCCESS; +} + static NSSItem * nss3certificate_getIdentifier(nssDecodedCert *dc) { @@ -476,9 +238,7 @@ nss3certificate_getIssuerIdentifier(nssDecodedCert *dc) CERTCertificate *c = (CERTCertificate *)dc->data; CERTAuthKeyID *cAuthKeyID; PRArenaPool *tmpArena = NULL; - SECItem issuerCertKey; NSSItem *rvID = NULL; - SECStatus secrv; tmpArena = PORT_NewArena(512); cAuthKeyID = CERT_FindAuthKeyIDExten(tmpArena, c); if (cAuthKeyID == NULL) { @@ -690,22 +450,21 @@ PK11_IsUserCert(PK11SlotInfo *, CERTCertificate *, CK_OBJECT_HANDLE); /* see pk11cert.c:pk11_HandleTrustObject */ static unsigned int -get_nss3trust_from_cktrust(CK_TRUST t) +get_nss3trust_from_nss4trust(CK_TRUST t) { unsigned int rt = 0; - if (t == CKT_NETSCAPE_TRUSTED) { + if (t == nssTrustLevel_Trusted) { rt |= CERTDB_VALID_PEER | CERTDB_TRUSTED; } - if (t == CKT_NETSCAPE_TRUSTED_DELEGATOR) { + if (t == nssTrustLevel_TrustedDelegator) { rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA /*| CERTDB_NS_TRUSTED_CA*/; } - if (t == CKT_NETSCAPE_VALID) { + if (t == nssTrustLevel_Valid) { rt |= CERTDB_VALID_PEER; } - if (t == CKT_NETSCAPE_VALID_DELEGATOR) { + if (t == nssTrustLevel_ValidDelegator) { rt |= CERTDB_VALID_CA; } - /* user */ return rt; } @@ -719,95 +478,61 @@ cert_trust_from_stan_trust(NSSTrust *t, PRArenaPool *arena) } rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust)); if (!rvTrust) return NULL; - rvTrust->sslFlags = get_nss3trust_from_cktrust(t->serverAuth); - client = get_nss3trust_from_cktrust(t->clientAuth); + rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth); + client = get_nss3trust_from_nss4trust(t->clientAuth); if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) { client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA); rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA; } rvTrust->sslFlags |= client; - rvTrust->emailFlags = get_nss3trust_from_cktrust(t->emailProtection); - rvTrust->objectSigningFlags = get_nss3trust_from_cktrust(t->codeSigning); + rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection); + rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning); return rvTrust; } -static int nsstoken_get_trust_order(NSSToken *token) -{ - PK11SlotInfo *slot; - SECMODModule *module; - slot = token->pk11slot; - module = PK11_GetModule(slot); - return module->trustOrder; -} - /* check all cert instances for private key */ static PRBool is_user_cert(NSSCertificate *c, CERTCertificate *cc) { PRBool isUser = PR_FALSE; - nssCryptokiInstance *instance; - nssListIterator *instances = c->object.instances; - for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); - instance != (nssCryptokiInstance *)NULL; - instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { + nssCryptokiObject **ip; + nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); + if (!instances) { + return PR_FALSE; + } + for (ip = instances; *ip; ip++) { + nssCryptokiObject *instance = *ip; if (PK11_IsUserCert(instance->token->pk11slot, cc, instance->handle)) { isUser = PR_TRUE; } } - nssListIterator_Finish(instances); + nssCryptokiObjectArray_Destroy(instances); return isUser; } CERTCertTrust * nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc) { - CERTCertTrust *rvTrust; + CERTCertTrust *rvTrust = NULL; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - NSSToken *tok; - NSSTrust *tokenTrust; - NSSTrust t; - nssListIterator *tokens; - int lastTrustOrder, myTrustOrder; - tokens = nssList_CreateIterator(td->tokenList); - if (!tokens) return NULL; - lastTrustOrder = 1<<16; /* just make it big */ - t.serverAuth = CKT_NETSCAPE_TRUST_UNKNOWN; - t.clientAuth = CKT_NETSCAPE_TRUST_UNKNOWN; - t.emailProtection = CKT_NETSCAPE_TRUST_UNKNOWN; - t.codeSigning = CKT_NETSCAPE_TRUST_UNKNOWN; - for (tok = (NSSToken *)nssListIterator_Start(tokens); - tok != (NSSToken *)NULL; - tok = (NSSToken *)nssListIterator_Next(tokens)) - { - tokenTrust = nssToken_FindTrustForCert(tok, NULL, c, - nssTokenSearchType_TokenOnly); - if (tokenTrust) { - myTrustOrder = nsstoken_get_trust_order(tok); - if (t.serverAuth == CKT_NETSCAPE_TRUST_UNKNOWN || - myTrustOrder < lastTrustOrder) { - t.serverAuth = tokenTrust->serverAuth; - } - if (t.clientAuth == CKT_NETSCAPE_TRUST_UNKNOWN || - myTrustOrder < lastTrustOrder) { - t.clientAuth = tokenTrust->clientAuth; - } - if (t.emailProtection == CKT_NETSCAPE_TRUST_UNKNOWN || - myTrustOrder < lastTrustOrder) { - t.emailProtection = tokenTrust->emailProtection; - } - if (t.codeSigning == CKT_NETSCAPE_TRUST_UNKNOWN || - myTrustOrder < lastTrustOrder) { - t.codeSigning = tokenTrust->codeSigning; - } - (void)nssTrust_Destroy(tokenTrust); - lastTrustOrder = myTrustOrder; + NSSTrust *t; + t = nssTrustDomain_FindTrustForCertificate(td, c); + if (t) { + rvTrust = cert_trust_from_stan_trust(t, cc->arena); + if (!rvTrust) { + nssTrust_Destroy(t); + return NULL; } + nssTrust_Destroy(t); + } else { + rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); + if (!rvTrust) { + return NULL; + } + memset(rvTrust, 0, sizeof(*rvTrust)); } - nssListIterator_Finish(tokens); - nssListIterator_Destroy(tokens); - rvTrust = cert_trust_from_stan_trust(&t, cc->arena); - if (!rvTrust) return NULL; if (is_user_cert(c, cc)) { + if (!rvTrust) { + } rvTrust->sslFlags |= CERTDB_USER; rvTrust->emailFlags |= CERTDB_USER; rvTrust->objectSigningFlags |= CERTDB_USER; @@ -818,15 +543,15 @@ nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc) static nssCryptokiInstance * get_cert_instance(NSSCertificate *c) { - nssCryptokiInstance *instance, *ci; - nssListIterator *instances = c->object.instances; + nssCryptokiObject *instance, **ci; + nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); + if (!instances) { + return NULL; + } instance = NULL; - for (ci = (nssCryptokiInstance *)nssListIterator_Start(instances); - ci != (nssCryptokiInstance *)NULL; - ci = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { + for (ci = instances; *ci; ci++) { if (!instance) { - instance = ci; + instance = nssCryptokiObject_Clone(*ci); } else { /* This only really works for two instances... But 3.4 can't * handle more anyway. The logic is, if there are multiple @@ -834,11 +559,12 @@ get_cert_instance(NSSCertificate *c) * a hardware device. */ if (PK11_IsInternal(instance->token->pk11slot)) { - instance = ci; + nssCryptokiObject_Destroy(instance); + instance = nssCryptokiObject_Clone(*ci); } } } - nssListIterator_Finish(instances); + nssCryptokiObjectArray_Destroy(instances); return instance; } @@ -860,7 +586,6 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced int nicklen, tokenlen, len; NSSUTF8 *tokenName = NULL; char *nick; - nicklen = nssUTF8_Size(stanNick, &nssrv); if (instance && !PK11_IsInternal(instance->token->pk11slot)) { tokenName = nssToken_GetName(instance->token); tokenlen = nssUTF8_Size(tokenName, &nssrv); @@ -868,16 +593,21 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced /* don't use token name for internal slot; 3.3 didn't */ tokenlen = 0; } - len = tokenlen + nicklen; - cc->nickname = PORT_ArenaAlloc(cc->arena, len); - nick = cc->nickname; - if (tokenName) { - memcpy(nick, tokenName, tokenlen-1); - nick += tokenlen-1; - *nick++ = ':'; + if (stanNick) { + nicklen = nssUTF8_Size(stanNick, &nssrv); + len = tokenlen + nicklen; + cc->nickname = PORT_ArenaAlloc(cc->arena, len); + nick = cc->nickname; + if (tokenName) { + memcpy(nick, tokenName, tokenlen-1); + nick += tokenlen-1; + *nick++ = ':'; + } + memcpy(nick, stanNick, nicklen-1); + cc->nickname[len-1] = '\0'; + } else { + cc->nickname = NULL; } - memcpy(nick, stanNick, nicklen-1); - cc->nickname[len-1] = '\0'; } if (context) { /* trust */ @@ -888,12 +618,18 @@ fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced } } else if (instance) { /* slot */ - cc->slot = PK11_ReferenceSlot(instance->token->pk11slot); + if (cc->slot != instance->token->pk11slot) { + if (cc->slot) { + PK11_FreeSlot(cc->slot); + } + cc->slot = PK11_ReferenceSlot(instance->token->pk11slot); + } cc->ownSlot = PR_TRUE; /* pkcs11ID */ cc->pkcs11ID = instance->handle; /* trust */ cc->trust = nssTrust_GetCERTCertTrustForCert(c, cc); + nssCryptokiObject_Destroy(instance); } /* database handle is now the trust domain */ cc->dbhandle = c->object.trustDomain; @@ -933,33 +669,39 @@ stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate) } NSS_IMPLEMENT CERTCertificate * +STAN_ForceCERTCertificateUpdate(NSSCertificate *c) +{ + return stan_GetCERTCertificate(c, PR_TRUE); +} + +NSS_IMPLEMENT CERTCertificate * STAN_GetCERTCertificate(NSSCertificate *c) { return stan_GetCERTCertificate(c, PR_FALSE); } -static CK_TRUST +static nssTrustLevel get_stan_trust(unsigned int t, PRBool isClientAuth) { if (isClientAuth) { if (t & CERTDB_TRUSTED_CLIENT_CA) { - return CKT_NETSCAPE_TRUSTED_DELEGATOR; + return nssTrustLevel_TrustedDelegator; } } else { if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) { - return CKT_NETSCAPE_TRUSTED_DELEGATOR; + return nssTrustLevel_TrustedDelegator; } } if (t & CERTDB_TRUSTED) { - return CKT_NETSCAPE_TRUSTED; + return nssTrustLevel_Trusted; } if (t & CERTDB_VALID_CA) { - return CKT_NETSCAPE_VALID_DELEGATOR; + return nssTrustLevel_ValidDelegator; } if (t & CERTDB_VALID_PEER) { - return CKT_NETSCAPE_VALID; + return nssTrustLevel_Valid; } - return CKT_NETSCAPE_UNTRUSTED; + return nssTrustLevel_NotTrusted; } NSS_EXTERN NSSCertificate * @@ -967,8 +709,8 @@ STAN_GetNSSCertificate(CERTCertificate *cc) { NSSCertificate *c; nssCryptokiInstance *instance; + nssPKIObject *pkiob; NSSArena *arena; - PRStatus nssrv; c = cc->nssCertificate; if (c) { return c; @@ -987,10 +729,12 @@ STAN_GetNSSCertificate(CERTCertificate *cc) } NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert); c->type = NSSCertificateType_PKIX; - nssrv = nssPKIObject_Initialize(&c->object, arena, cc->dbhandle, NULL); - if (nssrv != PR_SUCCESS) { - nssPKIObject_Destroy(&c->object); + pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL); + if (!pkiob) { + nssArena_Destroy(arena); + return NULL; } + c->object = *pkiob; nssItem_Create(arena, &c->issuer, cc->derIssuer.len, cc->derIssuer.data); nssItem_Create(arena, @@ -1012,7 +756,7 @@ STAN_GetNSSCertificate(CERTCertificate *cc) } if (cc->slot) { instance = nss_ZNEW(arena, nssCryptokiInstance); - instance->token = PK11Slot_GetNSSToken(cc->slot); + instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot)); instance->handle = cc->pkcs11ID; instance->isTokenObject = PR_TRUE; if (cc->nickname) { @@ -1021,10 +765,7 @@ STAN_GetNSSCertificate(CERTCertificate *cc) (NSSUTF8 *)cc->nickname, PORT_Strlen(cc->nickname)); } - nssList_Add(c->object.instanceList, instance); - /* XXX Fix this! */ - nssListIterator_Destroy(c->object.instances); - c->object.instances = nssList_CreateIterator(c->object.instanceList); + nssPKIObject_AddInstance(&c->object, instance); } c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc); cc->nssCertificate = c; @@ -1043,6 +784,8 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) CERTCertTrust *oldTrust; nssListIterator *tokens; PRBool moving_object; + nssCryptokiObject *newInstance; + nssPKIObject *pkiob; oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc); if (oldTrust) { if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) { @@ -1060,11 +803,12 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) arena = nssArena_Create(); if (!arena) return PR_FAILURE; nssTrust = nss_ZNEW(arena, NSSTrust); - nssrv = nssPKIObject_Initialize(&nssTrust->object, arena, NULL, NULL); - if (nssrv != PR_SUCCESS) { - nssPKIObject_Destroy(&nssTrust->object); + pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL); + if (!pkiob) { + nssArena_Destroy(arena); return PR_FAILURE; } + nssTrust->object = *pkiob; nssTrust->certificate = c; nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE); nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE); @@ -1078,7 +822,7 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) nssTrust_Destroy(nssTrust); return nssrv; } - if (nssList_Count(c->object.instanceList) == 0) { + if (c->object.numInstances == 0) { /* The context is the only instance, finished */ return nssrv; } @@ -1106,11 +850,39 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) /* this is kind of hacky. the softoken needs the cert * object in order to store trust. forcing it to be perm */ - NSSUTF8 *nickname = NSSCertificate_GetNickname(c, NULL); - nssrv = nssToken_ImportCertificate(tok, NULL, c, nickname, PR_TRUE); - if (nssrv != PR_SUCCESS) return nssrv; + NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); + NSSASCII7 *email = NULL; + + if (PK11_IsInternal(tok->pk11slot)) { + email = c->email; + } + newInstance = nssToken_ImportCertificate(tok, NULL, + NSSCertificateType_PKIX, + &c->id, + nickname, + &c->encoding, + &c->issuer, + &c->subject, + &c->serial, + email, + PR_TRUE); + if (!newInstance) { + return PR_FAILURE; + } + nssPKIObject_AddInstance(&c->object, newInstance); + } + newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, + &c->issuer, &c->serial, + nssTrust->serverAuth, + nssTrust->clientAuth, + nssTrust->codeSigning, + nssTrust->emailProtection, PR_TRUE); + if (newInstance) { + nssCryptokiObject_Destroy(newInstance); + nssrv = PR_SUCCESS; + } else { + nssrv = PR_FAILURE; } - nssrv = nssToken_ImportTrust(tok, NULL, nssTrust, PR_TRUE); } else { nssrv = PR_FAILURE; } @@ -1174,103 +946,6 @@ nssTrustDomain_TraverseCertificatesByNickname return nssrv; } -/* SEC_TraversePermCerts */ -NSS_IMPLEMENT PRStatus -nssTrustDomain_TraverseCertificates -( - NSSTrustDomain *td, - PRStatus (*callback)(NSSCertificate *c, void *arg), - void *arg -) -{ - PRStatus nssrv = PR_SUCCESS; - NSSToken *token; - nssList *certList; - nssTokenCertSearch search; - /* grab all cache certs (XXX please only do this here...) - * the alternative is to provide a callback through search that allows - * the token to query the cache for the cert during traversal. - */ - certList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsFromCache(td, certList); - /* set the search criteria */ - search.callback = callback; - search.cbarg = arg; - search.cached = certList; - search.searchType = nssTokenSearchType_TokenOnly; - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - nssrv = nssToken_TraverseCertificates(token, NULL, &search); - } - nssListIterator_Finish(td->tokens); - nssList_Destroy(certList); - return nssrv; -} - -#if 0 -static CK_CERTIFICATE_TYPE -get_cert_type(NSSCertificateType nssType) -{ - switch (nssType) { - case NSSCertificateType_PKIX: - return CKC_X_509; - default: - return CK_INVALID_HANDLE; /* Not really! CK_INVALID_HANDLE is not a - * type CK_CERTIFICATE_TYPE */ - } -} -#endif - -/* CERT_AddTempCertToPerm */ -NSS_EXTERN PRStatus -nssTrustDomain_AddTempCertToPerm -( - NSSCertificate *c -) -{ -#if 0 - NSSToken *token; - CK_CERTIFICATE_TYPE cert_type; - CK_ATTRIBUTE cert_template[] = - { - { CKA_CLASS, NULL, 0 }, - { CKA_CERTIFICATE_TYPE, NULL, 0 }, - { CKA_ID, NULL, 0 }, - { CKA_VALUE, NULL, 0 }, - { CKA_LABEL, NULL, 0 }, - { CKA_ISSUER, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, - { CKA_SERIAL_NUMBER, NULL, 0 } - }; - CK_ULONG ctsize; - ctsize = (CK_ULONG)(sizeof(cert_template) / sizeof(cert_template[0])); - /* XXX sanity checking needed */ - cert_type = get_cert_type(c->type); - /* Set up the certificate object */ - NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert); - NSS_CK_SET_ATTRIBUTE_VAR( cert_template, 1, cert_type); - NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 2, &c->id); - NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 3, &c->encoding); - NSS_CK_SET_ATTRIBUTE_UTF8(cert_template, 4, c->nickname); - NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 5, &c->issuer); - NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 6, &c->subject); - NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 7, &c->serial); - /* This is a hack, ignoring the 4.0 token ordering scheme */ - token = STAN_GetInternalToken(); - c->handle = nssToken_ImportObject(token, NULL, cert_template, ctsize); - if (c->handle == CK_INVALID_HANDLE) { - return PR_FAILURE; - } - c->token = token; - c->slot = token->slot; - /* Do the trust object */ - return PR_SUCCESS; -#endif - return PR_FAILURE; -} - static void cert_dump_iter(const void *k, void *v, void *a) { NSSCertificate *c = (NSSCertificate *)k; diff --git a/security/nss/lib/pki/pki3hack.h b/security/nss/lib/pki/pki3hack.h index c79fc747b..529c81e2b 100644 --- a/security/nss/lib/pki/pki3hack.h +++ b/security/nss/lib/pki/pki3hack.h @@ -75,29 +75,6 @@ STAN_LoadDefaultNSS3TrustDomain NSS_EXTERN void STAN_Shutdown(); -NSS_EXTERN void -STAN_DestroyNSSToken(NSSToken *token); - -NSS_EXTERN PRBool -nssToken_SearchCerts -( - NSSToken *token, - PRBool *notPresentOpt -); - -/* renewInstances -- if the cached token certs have multiple instances, - * don't destroy them. If this parameter is false, they will be destroyed - * anyway (used for clean shutdown). - */ -NSS_EXTERN void -nssToken_DestroyCertList(NSSToken *token, PRBool renewInstances); - -NSS_EXTERN void -nssCertificateList_DestroyTokenCerts(nssList *certList, NSSToken *token); - -NSS_EXTERN void -nssCertificateList_RemoveTokenCerts(nssList *certList, NSSToken *token); - NSS_EXTERN SECStatus STAN_AddModuleToDefaultTrustDomain ( @@ -111,6 +88,9 @@ STAN_RemoveModuleFromDefaultTrustDomain ); NSS_EXTERN CERTCertificate * +STAN_ForceCERTCertificateUpdate(NSSCertificate *c); + +NSS_EXTERN CERTCertificate * STAN_GetCERTCertificate(NSSCertificate *c); NSS_EXTERN NSSCertificate * @@ -122,6 +102,10 @@ nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc); NSS_EXTERN PRStatus STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust); +NSS_EXTERN PRStatus +nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der, NSSArena *arena, + NSSDER *issuer, NSSDER *serial); + /* exposing this */ NSS_EXTERN NSSCertificate * NSSCertificate_Create diff --git a/security/nss/lib/pki/pkim.h b/security/nss/lib/pki/pkim.h index 566381055..170a4d938 100644 --- a/security/nss/lib/pki/pkim.h +++ b/security/nss/lib/pki/pkim.h @@ -42,97 +42,546 @@ static const char PKIM_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "base.h" #endif /* BASE_H */ +#ifndef PKI_H +#include "pki.h" +#endif /* PKI_H */ + #ifndef PKITM_H #include "pkitm.h" #endif /* PKITM_H */ PR_BEGIN_EXTERN_C -NSS_EXTERN NSSToken * -STAN_GetDefaultCryptoToken +/* nssPKIObject + * + * This is the base object class, common to all PKI objects defined in + * in this module. Each object can be safely 'casted' to an nssPKIObject, + * then passed to these methods. + * + * nssPKIObject_Create + * nssPKIObject_Destroy + * nssPKIObject_AddRef + * nssPKIObject_AddInstance + * nssPKIObject_HasInstance + * nssPKIObject_GetTokens + * nssPKIObject_GetNicknameForToken + * nssPKIObject_RemoveInstanceForToken + * nssPKIObject_DeleteStoredObject + */ + +/* nssPKIObject_Create + * + * A generic PKI object. It must live in a trust domain. It may be + * initialized with a token instance, or alternatively in a crypto context. + */ +NSS_EXTERN nssPKIObject * +nssPKIObject_Create ( - void + NSSArena *arenaOpt, + nssCryptokiObject *instanceOpt, + NSSTrustDomain *td, + NSSCryptoContext *ccOpt ); -NSS_EXTERN nssHash * -nssHash_CreateCertificate +/* nssPKIObject_AddRef + */ +NSS_EXTERN nssPKIObject * +nssPKIObject_AddRef +( + nssPKIObject *object +); + +/* nssPKIObject_Destroy + * + * Returns true if object was destroyed. This notifies the subclass that + * all references are gone and it should delete any members it owns. + */ +NSS_EXTERN PRBool +nssPKIObject_Destroy +( + nssPKIObject *object +); + +/* nssPKIObject_AddInstance + * + * Add a token instance to the object, if it does not have it already. + */ +NSS_EXTERN PRStatus +nssPKIObject_AddInstance +( + nssPKIObject *object, + nssCryptokiObject *instance +); + +/* nssPKIObject_HasInstance + * + * Query the object for a token instance. + */ +NSS_EXTERN PRBool +nssPKIObject_HasInstance +( + nssPKIObject *object, + nssCryptokiObject *instance +); + +/* nssPKIObject_GetTokens + * + * Get all tokens which have an instance of the object. + */ +NSS_EXTERN NSSToken ** +nssPKIObject_GetTokens +( + nssPKIObject *object, + PRStatus *statusOpt +); + +/* nssPKIObject_GetNicknameForToken + * + * tokenOpt == NULL means take the first available, otherwise return the + * nickname for the specified token. + */ +NSS_EXTERN NSSUTF8 * +nssPKIObject_GetNicknameForToken +( + nssPKIObject *object, + NSSToken *tokenOpt +); + +/* nssPKIObject_RemoveInstanceForToken + * + * Remove the instance of the object on the specified token. + */ +NSS_EXTERN PRStatus +nssPKIObject_RemoveInstanceForToken +( + nssPKIObject *object, + NSSToken *token +); + +/* nssPKIObject_DeleteStoredObject + * + * Delete all token instances of the object, as well as any crypto context + * instances (TODO). If any of the instances are read-only, or if the + * removal fails, the object will keep those instances. 'isFriendly' refers + * to the object -- can this object be removed from a friendly token without + * login? For example, certificates are friendly, private keys are not. + * Note that if the token is not friendly, authentication will be required + * regardless of the value of 'isFriendly'. + */ +NSS_EXTERN PRStatus +nssPKIObject_DeleteStoredObject +( + nssPKIObject *object, + NSSCallback *uhh, + PRBool isFriendly +); + +#ifdef NSS_3_4_CODE +NSS_EXTERN nssCryptokiObject ** +nssPKIObject_GetInstances +( + nssPKIObject *object +); +#endif + +NSS_EXTERN NSSCertificate ** +nssTrustDomain_FindCertificatesByID +( + NSSTrustDomain *td, + NSSItem *id, + NSSCertificate **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSCRL ** +nssTrustDomain_FindCRLsBySubject +( + NSSTrustDomain *td, + NSSDER *subject +); + +/* module-private nsspki methods */ + +NSS_EXTERN NSSCryptoContext * +nssCryptoContext_Create +( + NSSTrustDomain *td, + NSSCallback *uhhOpt +); + +/* XXX for the collection */ +NSS_EXTERN NSSCertificate * +nssCertificate_Create +( + nssPKIObject *object +); + +NSS_EXTERN PRStatus +nssCertificate_SetCertTrust +( + NSSCertificate *c, + NSSTrust *trust +); + +NSS_EXTERN nssDecodedCert * +nssCertificate_GetDecoding +( + NSSCertificate *c +); + +NSS_EXTERN nssDecodedCert * +nssDecodedCert_Create ( NSSArena *arenaOpt, - PRUint32 numBuckets + NSSDER *encoding, + NSSCertificateType type +); + +NSS_EXTERN PRStatus +nssDecodedCert_Destroy +( + nssDecodedCert *dc ); -/* Token ordering routines */ +NSS_EXTERN NSSTrust * +nssTrust_Create +( + nssPKIObject *object +); -/* - * Given a crypto algorithm, return the preferred token for performing - * the crypto operation. +NSS_EXTERN NSSCRL * +nssCRL_Create +( + nssPKIObject *object +); + +NSS_EXTERN NSSCRL * +nssCRL_AddRef +( + NSSCRL *crl +); + +NSS_EXTERN PRStatus +nssCRL_Destroy +( + NSSCRL *crl +); + +NSS_EXTERN PRStatus +nssCRL_DeleteStoredObject +( + NSSCRL *crl, + NSSCallback *uhh +); + +NSS_EXTERN NSSPrivateKey * +nssPrivateKey_Create +( + nssPKIObject *o +); + +NSS_EXTERN NSSDER * +nssCRL_GetEncoding +( + NSSCRL *crl +); + +NSS_EXTERN NSSPublicKey * +nssPublicKey_Create +( + nssPKIObject *object +); + +/* nssCertificateArray + * + * These are being thrown around a lot, might as well group together some + * functionality. + * + * nssCertificateArray_Destroy + * nssCertificateArray_Join + * nssCertificateArray_FindBestCertificate + * nssCertificateArray_Traverse + */ + +/* nssCertificateArray_Destroy + * + * Will destroy the array and the certs within it. If the array was created + * in an arena, will *not* (of course) destroy the arena. However, is safe + * to call this method on an arena-allocated array. + */ +NSS_EXTERN void +nssCertificateArray_Destroy +( + NSSCertificate **certs +); + +/* nssCertificateArray_Join + * + * Join two arrays into one. The two arrays, certs1 and certs2, should + * be considered invalid after a call to this function (they may be destroyed + * as part of the join). certs1 and/or certs2 may be NULL. Safe to + * call with arrays allocated in an arena, the result will also be in the + * arena. + */ +NSS_EXTERN NSSCertificate ** +nssCertificateArray_Join +( + NSSCertificate **certs1, + NSSCertificate **certs2 +); + +/* nssCertificateArray_FindBestCertificate + * + * Use the usual { time, usage, policies } to find the best cert in the + * array. + */ +NSS_EXTERN NSSCertificate * +nssCertificateArray_FindBestCertificate +( + NSSCertificate **certs, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt +); + +/* nssCertificateArray_Traverse + * + * Do the callback for each cert, terminate the traversal if the callback + * fails. */ -NSS_EXTERN NSSToken * -nssTrustDomain_GetCryptoToken +NSS_EXTERN PRStatus +nssCertificateArray_Traverse +( + NSSCertificate **certs, + PRStatus (* callback)(NSSCertificate *c, void *arg), + void *arg +); + +NSS_EXTERN void +nssCRLArray_Destroy +( + NSSCRL **crls +); + +/* nssPKIObjectCollection + * + * This is a handy way to group objects together and perform operations + * on them. It can also handle "proto-objects"-- references to + * objects instances on tokens, where the actual object hasn't + * been formed yet. + * + * nssCertificateCollection_Create + * nssPrivateKeyCollection_Create + * nssPublicKeyCollection_Create + * + * If this was a language that provided for inheritance, each type would + * inherit all of the following methods. Instead, there is only one + * type (nssPKIObjectCollection), shared among all. This may cause + * confusion; an alternative would be to define all of the methods + * for each subtype (nssCertificateCollection_Destroy, ...), but that doesn't + * seem worth the code bloat.. It is left up to the caller to remember + * what type of collection he/she is dealing with. + * + * nssPKIObjectCollection_Destroy + * nssPKIObjectCollection_Count + * nssPKIObjectCollection_AddObject + * nssPKIObjectCollection_AddInstances + * nssPKIObjectCollection_Traverse + * + * Back to type-specific methods. + * + * nssPKIObjectCollection_GetCertificates + * nssPKIObjectCollection_GetCRLs + * nssPKIObjectCollection_GetPrivateKeys + * nssPKIObjectCollection_GetPublicKeys + */ + +/* nssCertificateCollection_Create + * + * Create a collection of certificates in the specified trust domain. + * Optionally provide a starting set of certs. + */ +NSS_EXTERN nssPKIObjectCollection * +nssCertificateCollection_Create ( NSSTrustDomain *td, - NSSAlgorithmAndParameters *ap + NSSCertificate **certsOpt ); -/* The following routines are used to obtain the preferred token on which - * to store particular objects. +/* nssCRLCollection_Create + * + * Create a collection of CRLs/KRLs in the specified trust domain. + * Optionally provide a starting set of CRLs. */ +NSS_EXTERN nssPKIObjectCollection * +nssCRLCollection_Create +( + NSSTrustDomain *td, + NSSCRL **crlsOpt +); -/* - * Find the preferred token for storing user certificates. +/* nssPrivateKeyCollection_Create + * + * Create a collection of private keys in the specified trust domain. + * Optionally provide a starting set of keys. */ -NSS_EXTERN NSSToken * -nssTrustDomain_GetUserCertToken +NSS_EXTERN nssPKIObjectCollection * +nssPrivateKeyCollection_Create ( - NSSTrustDomain *td + NSSTrustDomain *td, + NSSPrivateKey **pvkOpt ); -/* - * Find the preferred token for storing email certificates. +/* nssPublicKeyCollection_Create + * + * Create a collection of public keys in the specified trust domain. + * Optionally provide a starting set of keys. */ -NSS_EXTERN NSSToken * -nssTrustDomain_GetEmailCertToken +NSS_EXTERN nssPKIObjectCollection * +nssPublicKeyCollection_Create ( - NSSTrustDomain *td + NSSTrustDomain *td, + NSSPublicKey **pvkOpt ); -/* - * Find the preferred token for storing SSL certificates. +/* nssPKIObjectCollection_Destroy */ -NSS_EXTERN NSSToken * -nssTrustDomain_GetSSLCertToken +NSS_EXTERN void +nssPKIObjectCollection_Destroy ( - NSSTrustDomain *td + nssPKIObjectCollection *collection ); -/* - * Find the preferred token for storing root certificates. +/* nssPKIObjectCollection_Count */ -NSS_EXTERN NSSToken * -nssTrustDomain_GetRootCertToken +NSS_EXTERN PRUint32 +nssPKIObjectCollection_Count ( - NSSTrustDomain *td + nssPKIObjectCollection *collection ); -/* - * Find the preferred token for storing private keys. +NSS_EXTERN PRStatus +nssPKIObjectCollection_AddObject +( + nssPKIObjectCollection *collection, + nssPKIObject *object +); + +/* nssPKIObjectCollection_AddInstances + * + * Add a set of object instances to the collection. The instances + * will be sorted into any existing certs/proto-certs that may be in + * the collection. The instances will be absorbed by the collection, + * the array should not be used after this call (except to free it). + * + * Failure means the collection is in an invalid state. + * + * numInstances = 0 means the array is NULL-terminated */ -NSS_EXTERN NSSToken * -nssTrustDomain_GetPrivateKeyToken +NSS_EXTERN PRStatus +nssPKIObjectCollection_AddInstances ( - NSSTrustDomain *td + nssPKIObjectCollection *collection, + nssCryptokiObject **instances, + PRUint32 numInstances ); -/* - * Find the preferred token for storing symmetric keys. +/* nssPKIObjectCollection_Traverse */ -NSS_EXTERN NSSToken * -nssTrustDomain_GetSymmetricKeyToken +NSS_EXTERN PRStatus +nssPKIObjectCollection_Traverse ( - NSSTrustDomain *td + nssPKIObjectCollection *collection, + nssPKIObjectCallback *callback ); -/* Certificate cache routines */ +/* This function is being added for NSS 3.5. It corresponds to the function + * nssToken_TraverseCertificates. The idea is to use the collection during + * a traversal, creating certs each time a new instance is added for which + * a cert does not already exist. + */ +NSS_EXTERN PRStatus +nssPKIObjectCollection_AddInstanceAsObject +( + nssPKIObjectCollection *collection, + nssCryptokiObject *instance +); + +/* nssPKIObjectCollection_GetCertificates + * + * Get all of the certificates in the collection. + */ +NSS_EXTERN NSSCertificate ** +nssPKIObjectCollection_GetCertificates +( + nssPKIObjectCollection *collection, + NSSCertificate **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSCRL ** +nssPKIObjectCollection_GetCRLs +( + nssPKIObjectCollection *collection, + NSSCRL **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSPrivateKey ** +nssPKIObjectCollection_GetPrivateKeys +( + nssPKIObjectCollection *collection, + NSSPrivateKey **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSPublicKey ** +nssPKIObjectCollection_GetPublicKeys +( + nssPKIObjectCollection *collection, + NSSPublicKey **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN NSSTime * +NSSTime_Now +( + NSSTime *timeOpt +); + +NSS_EXTERN NSSTime * +NSSTime_SetPRTime +( + NSSTime *timeOpt, + PRTime prTime +); + +NSS_EXTERN PRTime +NSSTime_GetPRTime +( + NSSTime *time +); + +NSS_EXTERN nssHash * +nssHash_CreateCertificate +( + NSSArena *arenaOpt, + PRUint32 numBuckets +); + +/* 3.4 Certificate cache routines */ + +NSS_EXTERN PRStatus +nssTrustDomain_InitializeCache +( + NSSTrustDomain *td, + PRUint32 cacheSize +); NSS_EXTERN PRStatus nssTrustDomain_AddCertsToCache @@ -173,6 +622,13 @@ nssTrustDomain_RemoveTokenCertsFromCache NSSToken *token ); +NSS_EXTERN PRStatus +nssTrustDomain_UpdateCachedTokenCerts +( + NSSTrustDomain *td, + NSSToken *token +); + /* * Find all cached certs with this nickname (label). */ @@ -238,54 +694,11 @@ nssTrustDomain_GetCertsFromCache nssList *certListOpt ); -NSS_EXTERN PRStatus -nssCertificate_SetCertTrust -( - NSSCertificate *c, - NSSTrust *trust -); - -NSS_EXTERN nssDecodedCert * -nssCertificate_GetDecoding -( - NSSCertificate *c -); - -NSS_EXTERN nssDecodedCert * -nssDecodedCert_Create -( - NSSArena *arenaOpt, - NSSDER *encoding, - NSSCertificateType type -); - -NSS_EXTERN PRStatus -nssDecodedCert_Destroy -( - nssDecodedCert *dc -); - -NSS_EXTERN void -nssBestCertificate_SetArgs -( - nssBestCertificateCB *best, - NSSTime *timeOpt, - NSSUsage *usage, - NSSPolicies *policies -); - -NSS_EXTERN PRStatus -nssBestCertificate_Callback -( - NSSCertificate *c, - void *arg -); - -NSS_EXTERN PRStatus -nssCertificateList_DoCallback +NSS_EXTERN void +nssTrustDomain_DumpCacheInfo ( - nssList *certList, - PRStatus (* callback)(NSSCertificate *c, void *arg), + NSSTrustDomain *td, + void (* cert_dump_iter)(const void *, void *, void *), void *arg ); @@ -295,54 +708,6 @@ nssCertificateList_AddReferences nssList *certList ); -NSS_EXTERN PRStatus -nssPKIObject_Initialize -( - struct nssPKIObjectBaseStr *object, - NSSArena *arena, - NSSTrustDomain *td, - NSSCryptoContext *cc -); - -NSS_EXTERN void -nssPKIObject_AddRef -( - struct nssPKIObjectBaseStr *object -); - -NSS_EXTERN PRBool -nssPKIObject_Destroy -( - struct nssPKIObjectBaseStr *object -); - -NSS_EXTERN NSSTime * -NSSTime_Now -( - NSSTime *timeOpt -); - -NSS_EXTERN NSSTime * -NSSTime_SetPRTime -( - NSSTime *timeOpt, - PRTime prTime -); - -NSS_EXTERN PRTime -NSSTime_GetPRTime -( - NSSTime *time -); - -NSS_EXTERN void -nssTrustDomain_DumpCacheInfo -( - NSSTrustDomain *td, - void (* cert_dump_iter)(const void *, void *, void *), - void *arg -); - PR_END_EXTERN_C #endif /* PKIM_H */ diff --git a/security/nss/lib/pki/pkistore.c b/security/nss/lib/pki/pkistore.c index 0b1463fcb..a045b0a68 100644 --- a/security/nss/lib/pki/pkistore.c +++ b/security/nss/lib/pki/pkistore.c @@ -435,8 +435,8 @@ static void match_nickname(const void *k, void *v, void *a) nssList *subjectList = (nssList *)v; struct nickname_template_str *nt = (struct nickname_template_str *)a; nssrv = nssList_GetArray(subjectList, (void **)&c, 1); - nickname = NSSCertificate_GetNickname(c, NULL); - if (nssrv == PR_SUCCESS && + nickname = nssCertificate_GetNickname(c, NULL); + if (nssrv == PR_SUCCESS && nickname && nssUTF8_Equal(nickname, nt->nickname, &nssrv)) { nt->subjectList = subjectList; diff --git a/security/nss/lib/pki/pkit.h b/security/nss/lib/pki/pkit.h index 1e0f98a4f..f8bd067b9 100644 --- a/security/nss/lib/pki/pkit.h +++ b/security/nss/lib/pki/pkit.h @@ -71,13 +71,6 @@ static const char PKIT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; PR_BEGIN_EXTERN_C -typedef struct nssDecodedCertStr nssDecodedCert; - -typedef struct nssCertificateStoreStr nssCertificateStore; - -/* How wide is the scope of this? */ -typedef struct nssSMIMEProfileStr nssSMIMEProfile; - /* * A note on ephemeral certs * @@ -93,17 +86,25 @@ typedef struct nssSMIMEProfileStr nssSMIMEProfile; * for each object. */ -/* The common data from which all objects inherit */ -struct nssPKIObjectBaseStr +/* nssPKIObject + * + * This is the base object class, common to all PKI objects defined in + * nsspkit.h + */ +struct nssPKIObjectStr { /* The arena for all object memory */ NSSArena *arena; - /* Thread-safe reference counting */ - PZLock *lock; + /* Atomically incremented/decremented reference counting */ PRInt32 refCount; - /* List of nssCryptokiInstance's of the object */ - nssList *instanceList; - nssListIterator *instances; + /* lock protects the array of nssCryptokiInstance's of the object */ + PZLock *lock; + /* XXX with LRU cache, this cannot be guaranteed up-to-date. It cannot + * be compared against the update level of the trust domain, since it is + * also affected by import/export. Where is this array needed? + */ + nssCryptokiObject **instances; + PRUint32 numInstances; /* The object must live in a trust domain */ NSSTrustDomain *trustDomain; /* The object may live in a crypto context */ @@ -112,9 +113,18 @@ struct nssPKIObjectBaseStr NSSUTF8 *tempName; }; +typedef struct nssDecodedCertStr nssDecodedCert; + +typedef struct nssCertificateStoreStr nssCertificateStore; + +/* How wide is the scope of this? */ +typedef struct nssSMIMEProfileStr nssSMIMEProfile; + +typedef struct nssPKIObjectStr nssPKIObject; + struct NSSTrustStr { - struct nssPKIObjectBaseStr object; + nssPKIObject object; NSSCertificate *certificate; nssTrustLevel serverAuth; nssTrustLevel clientAuth; @@ -124,7 +134,7 @@ struct NSSTrustStr struct nssSMIMEProfileStr { - struct nssPKIObjectBaseStr object; + nssPKIObject object; NSSCertificate *certificate; NSSASCII7 *email; NSSDER *subject; @@ -134,7 +144,7 @@ struct nssSMIMEProfileStr struct NSSCertificateStr { - struct nssPKIObjectBaseStr object; + nssPKIObject object; NSSCertificateType type; NSSItem id; NSSBER encoding; @@ -156,7 +166,7 @@ typedef struct nssTDCertificateCacheStr nssTDCertificateCache; struct NSSTrustDomainStr { PRInt32 refCount; NSSArena *arena; - NSSCallback defaultCallback; + NSSCallback *defaultCallback; nssList *tokenList; nssListIterator *tokens; nssTDCertificateCache *cache; @@ -180,6 +190,15 @@ struct NSSTimeStr { PRTime prTime; }; +struct NSSCRLStr { + nssPKIObject object; + NSSDER encoding; + NSSUTF8 *url; + PRBool isKRL; +}; + +typedef struct NSSCRLStr NSSCRL; + struct NSSPoliciesStr; struct NSSAlgorithmAndParametersStr; diff --git a/security/nss/lib/pki/pkitm.h b/security/nss/lib/pki/pkitm.h index a943fd834..d163923e6 100644 --- a/security/nss/lib/pki/pkitm.h +++ b/security/nss/lib/pki/pkitm.h @@ -104,6 +104,19 @@ struct nssBestCertificateCBStr { NSSPolicies *policies; }; +typedef struct nssPKIObjectCollectionStr nssPKIObjectCollection; + +typedef struct +{ + union { + PRStatus (* cert)(NSSCertificate *c, void *arg); + PRStatus (* crl)(NSSCRL *crl, void *arg); + PRStatus (* pvkey)(NSSPrivateKey *vk, void *arg); + PRStatus (* pbkey)(NSSPublicKey *bk, void *arg); + } func; + void *arg; +} nssPKIObjectCallback; + PR_END_EXTERN_C #endif /* PKITM_H */ diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c index e34c6403a..0adc08e06 100644 --- a/security/nss/lib/pki/tdcache.c +++ b/security/nss/lib/pki/tdcache.c @@ -61,6 +61,8 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #ifdef NSS_3_4_CODE #include "cert.h" +#include "dev.h" +#include "pki3hack.h" #endif #ifdef DEBUG_CACHE @@ -124,6 +126,7 @@ struct cache_entry_str PRUint32 hits; PRTime lastHit; NSSArena *arena; + NSSUTF8 *nickname; }; typedef struct cache_entry_str cache_entry; @@ -139,6 +142,7 @@ new_cache_entry(NSSArena *arena, void *value, PRBool ownArena) if (ownArena) { ce->arena = arena; } + ce->nickname = NULL; } return ce; } @@ -274,6 +278,7 @@ remove_subject_entry nssTDCertificateCache *cache, NSSCertificate *cert, nssList **subjectList, + NSSUTF8 **nickname, NSSArena **arena ) { @@ -287,6 +292,7 @@ remove_subject_entry /* Remove the cert from the subject hash */ nssList_Remove(ce->entry.list, cert); *subjectList = ce->entry.list; + *nickname = ce->nickname; *arena = ce->arena; nssrv = PR_SUCCESS; #ifdef DEBUG_CACHE @@ -303,12 +309,11 @@ static PRStatus remove_nickname_entry ( nssTDCertificateCache *cache, - NSSCertificate *cert, + NSSUTF8 *nickname, nssList *subjectList ) { PRStatus nssrv; - NSSUTF8 *nickname = NSSCertificate_GetNickname(cert, NULL); if (nickname) { nssHash_Remove(cache->nickname, nickname); nssrv = PR_SUCCESS; @@ -373,6 +378,8 @@ nssTrustDomain_RemoveCertFromCache PRStatus nssrv; cache_entry *ce; NSSArena *arena; + NSSUTF8 *nickname; + #ifdef DEBUG_CACHE log_cert_ref("attempt to remove cert", cert); #endif @@ -392,13 +399,14 @@ nssTrustDomain_RemoveCertFromCache if (nssrv != PR_SUCCESS) { goto loser; } - nssrv = remove_subject_entry(td->cache, cert, &subjectList, &arena); + nssrv = remove_subject_entry(td->cache, cert, &subjectList, + &nickname, &arena); if (nssrv != PR_SUCCESS) { goto loser; } if (nssList_Count(subjectList) == 0) { PRStatus nssrv2; - nssrv = remove_nickname_entry(td->cache, cert, subjectList); + nssrv = remove_nickname_entry(td->cache, nickname, subjectList); nssrv2 = remove_email_entry(td->cache, cert, subjectList); #ifndef NSS_3_4_CODE /* XXX Again, 3.4 allows for certs w/o either nickname or email */ @@ -441,23 +449,39 @@ nssTrustDomain_FlushCache { } -struct token_cert_destructor { - nssTDCertificateCache *cache; +struct token_cert_dtor { NSSToken *token; + nssTDCertificateCache *cache; + NSSCertificate **certs; + PRUint32 numCerts, arrSize; }; static void remove_token_certs(const void *k, void *v, void *a) { -#if 0 - struct NSSItem *identifier = (struct NSSItem *)k; - NSSCertificate *c = (NSSCertificate *)v; - struct token_cert_destructor *tcd = (struct token_cert_destructor *)a; - if (c->token == tcd->token) { - nssHash_Remove(tcd->cache->issuerAndSN, identifier); - /* remove from the other hashes */ + NSSCertificate *c = (NSSCertificate *)k; + nssPKIObject *object = &c->object; + struct token_cert_dtor *dtor = a; + PRUint32 i; + PZ_Lock(object->lock); + for (i=0; i<object->numInstances; i++) { + if (object->instances[i]->token == dtor->token) { + nssCryptokiObject_Destroy(object->instances[i]); + object->instances[i] = object->instances[object->numInstances-1]; + object->instances[object->numInstances-1] = NULL; + object->numInstances--; + dtor->certs[dtor->numCerts++] = nssCertificate_AddRef(c); + if (dtor->numCerts == dtor->arrSize) { + dtor->arrSize *= 2; + dtor->certs = nss_ZREALLOCARRAY(dtor->certs, + NSSCertificate *, + dtor->arrSize); + } + break; + } } -#endif + PZ_Unlock(object->lock); + return; } /* @@ -471,12 +495,72 @@ nssTrustDomain_RemoveTokenCertsFromCache NSSToken *token ) { - struct token_cert_destructor tcd; - tcd.cache = td->cache; - tcd.token = token; + NSSCertificate **certs; + PRUint32 i, arrSize = 10; + struct token_cert_dtor dtor; + certs = nss_ZNEWARRAY(NULL, NSSCertificate *, arrSize); + if (!certs) { + return PR_FAILURE; + } + dtor.cache = td->cache; + dtor.token = token; + dtor.certs = certs; + dtor.numCerts = 0; + dtor.arrSize = arrSize; PZ_Lock(td->cache->lock); - nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, (void *)&tcd); + nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, (void *)&dtor); PZ_Unlock(td->cache->lock); + for (i=0; i<dtor.numCerts; i++) { + if (dtor.certs[i]->object.numInstances == 0) { + nssTrustDomain_RemoveCertFromCache(td, dtor.certs[i]); + } else { + STAN_ForceCERTCertificateUpdate(dtor.certs[i]); + } + nssCertificate_Destroy(dtor.certs[i]); + } + nss_ZFreeIf(dtor.certs); + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssTrustDomain_UpdateCachedTokenCerts +( + NSSTrustDomain *td, + NSSToken *token +) +{ + NSSCertificate **cp, **cached = NULL; + nssList *certList; + PRUint32 count; + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) return PR_FAILURE; + (void *)nssTrustDomain_GetCertsFromCache(td, certList); + count = nssList_Count(certList); + if (count > 0) { + cached = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); + if (!cached) { + return PR_FAILURE; + } + nssList_GetArray(certList, (void **)cached, count); + nssList_Destroy(certList); + for (cp = cached; *cp; cp++) { + nssCryptokiObject *instance; + NSSCertificate *c = *cp; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + instance = nssToken_FindCertificateByIssuerAndSerialNumber( + token, + NULL, + &c->issuer, + &c->serial, + tokenOnly, + NULL); + if (instance) { + nssPKIObject_AddInstance(&c->object, instance); + STAN_ForceCERTCertificateUpdate(c); + } + } + nssCertificateArray_Destroy(cached); + } return PR_SUCCESS; } @@ -502,6 +586,7 @@ add_subject_entry NSSArena *arena, nssTDCertificateCache *cache, NSSCertificate *cert, + NSSUTF8 *nickname, nssList **subjectList ) { @@ -529,6 +614,9 @@ add_subject_entry if (!ce) { return PR_FAILURE; } + if (nickname) { + ce->nickname = nssUTF8_Duplicate(nickname, arena); + } nssList_SetSortFunction(list, subject_list_sort); /* Add the cert entry to this list of subjects */ nssrv = nssList_AddUnique(list, cert); @@ -557,12 +645,11 @@ add_nickname_entry ( NSSArena *arena, nssTDCertificateCache *cache, - NSSCertificate *cert, + NSSUTF8 *certNickname, nssList *subjectList ) { PRStatus nssrv = PR_SUCCESS; - NSSUTF8 *certNickname = NSSCertificate_GetNickname(cert, NULL); cache_entry *ce; ce = (cache_entry *)nssHash_Lookup(cache->nickname, certNickname); if (ce) { @@ -654,7 +741,7 @@ add_email_entry extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE; -static PRStatus +static NSSCertificate * add_cert_to_cache ( NSSTrustDomain *td, @@ -662,21 +749,29 @@ add_cert_to_cache ) { NSSArena *arena = NULL; - nssList *subjectList; + nssList *subjectList = NULL; PRStatus nssrv; PRUint32 added = 0; + cache_entry *ce; + NSSCertificate *rvCert = NULL; + NSSUTF8 *certNickname = nssCertificate_GetNickname(cert, NULL); + PZ_Lock(td->cache->lock); /* If it exists in the issuer/serial hash, it's already in all */ - if (nssHash_Exists(td->cache->issuerAndSN, cert)) { + ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, cert); + if (ce) { + ce->hits++; + ce->lastHit = PR_Now(); + rvCert = nssCertificate_AddRef(ce->entry.cert); #ifdef DEBUG_CACHE log_cert_ref("attempted to add cert already in cache", cert); #endif PZ_Unlock(td->cache->lock); - /* collision - most likely, somebody else already added the cert + /* collision - somebody else already added the cert * to the cache before this thread got around to it. */ - nss_SetError(NSS_ERROR_CERTIFICATE_IN_CACHE); - return PR_FAILURE; + nssCertificate_Destroy(cert); + return rvCert; } /* create a new cache entry for this cert within the cert's arena*/ nssrv = add_issuer_and_serial_entry(cert->object.arena, td->cache, cert); @@ -690,7 +785,8 @@ add_cert_to_cache goto loser; } /* create a new subject list for this cert, or add to existing */ - nssrv = add_subject_entry(arena, td->cache, cert, &subjectList); + nssrv = add_subject_entry(arena, td->cache, cert, + certNickname, &subjectList); if (nssrv != PR_SUCCESS) { goto loser; } @@ -698,9 +794,9 @@ add_cert_to_cache /* If a new subject entry was created, also need nickname and/or email */ if (subjectList != NULL) { PRBool handle = PR_FALSE; - NSSUTF8 *certNickname = NSSCertificate_GetNickname(cert, NULL); if (certNickname) { - nssrv = add_nickname_entry(arena, td->cache, cert, subjectList); + nssrv = add_nickname_entry(arena, td->cache, + certNickname, subjectList); if (nssrv != PR_SUCCESS) { goto loser; } @@ -727,9 +823,9 @@ add_cert_to_cache } #endif } - nssCertificate_AddRef(cert); + rvCert = nssCertificate_AddRef(cert); PZ_Unlock(td->cache->lock); - return nssrv; + return rvCert; loser: /* Remove any handles that have been created */ subjectList = NULL; @@ -737,10 +833,11 @@ loser: (void)remove_issuer_and_serial_entry(td->cache, cert); } if (added >= 2) { - (void)remove_subject_entry(td->cache, cert, &subjectList, &arena); + (void)remove_subject_entry(td->cache, cert, &subjectList, + &certNickname, &arena); } if (added == 3 || added == 5) { - (void)remove_nickname_entry(td->cache, cert, subjectList); + (void)remove_nickname_entry(td->cache, certNickname, subjectList); } if (added >= 4) { (void)remove_email_entry(td->cache, cert, subjectList); @@ -753,7 +850,7 @@ loser: nssArena_Destroy(arena); } PZ_Unlock(td->cache->lock); - return PR_FAILURE; + return NULL; } NSS_IMPLEMENT PRStatus @@ -765,32 +862,14 @@ nssTrustDomain_AddCertsToCache ) { PRUint32 i; - NSSError e; + NSSCertificate *c; for (i=0; i<numCerts && certs[i]; i++) { - if (add_cert_to_cache(td, certs[i]) != PR_SUCCESS) { - if ((e = NSS_GetError()) == NSS_ERROR_CERTIFICATE_IN_CACHE) { - /* collision - delete and replace the cert here in favor - * of the already cached entry. This is safe as long as - * the cert being added here only has a single reference. - * This should be the case as this function is only called - * immediately following a traversal and before any certs - * are returned to the caller. - */ - NSSCertificate *c; - c = nssTrustDomain_GetCertForIssuerAndSNFromCache(td, - &certs[i]->issuer, - &certs[i]->serial); - if (c != certs[i]) { - NSSCertificate_Destroy(certs[i]); - certs[i] = c; - } else { - NSSCertificate_Destroy(c); - } - nss_ClearErrorStack(); - continue; - } + c = add_cert_to_cache(td, certs[i]); + if (c == NULL) { return PR_FAILURE; - } + } else { + certs[i] = c; + } } return PR_SUCCESS; } diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c index f3ebc5125..c5e3dc337 100644 --- a/security/nss/lib/pki/trustdomain.c +++ b/security/nss/lib/pki/trustdomain.c @@ -35,41 +35,42 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #endif /* DEBUG */ -#ifndef NSSPKI_H -#include "nsspki.h" -#endif /* NSSPKI_H */ - -#ifndef PKI_H -#include "pki.h" -#endif /* PKI_H */ +#ifndef DEV_H +#include "dev.h" +#endif /* DEV_H */ #ifndef PKIM_H #include "pkim.h" #endif /* PKIM_H */ -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ - -#ifndef CKHELPER_H -#include "ckhelper.h" -#endif /* CKHELPER_H */ +#ifndef PKI1T_H +#include "pki1t.h" +#endif /* PKI1T_H */ #ifdef NSS_3_4_CODE #include "cert.h" #include "pki3hack.h" #endif -extern const NSSError NSS_ERROR_NOT_FOUND; - #define NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE 32 -NSS_EXTERN PRStatus -nssTrustDomain_InitializeCache -( - NSSTrustDomain *td, - PRUint32 cacheSize -); +#ifdef PURE_STAN_BUILD +struct NSSTrustDomainStr { + PRInt32 refCount; + NSSArena *arena; + NSSCallback *defaultCallback; + struct { + nssSlotList *forCerts; + nssSlotList *forCiphers; + nssSlotList *forTrust; + } slots; + nssCertificateCache *cache; +}; +#endif + +extern const NSSError NSS_ERROR_NOT_FOUND; + +typedef PRUint32 nssUpdateLevel; NSS_IMPLEMENT NSSTrustDomain * NSSTrustDomain_Create @@ -90,9 +91,9 @@ NSSTrustDomain_Create if (!rvTD) { goto loser; } + nssTrustDomain_InitializeCache(rvTD, NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE); rvTD->arena = arena; rvTD->refCount = 1; - nssTrustDomain_InitializeCache(rvTD, NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE); #ifdef NSS_3_4_CODE rvTD->statusConfig = NULL; #endif @@ -106,13 +107,9 @@ static void token_destructor(void *t) { NSSToken *tok = (NSSToken *)t; -#ifdef NSS_3_4_CODE /* in 3.4, also destroy the slot (managed separately) */ (void)nssSlot_Destroy(tok->slot); - STAN_DestroyNSSToken(tok); -#else - (void)nssToken_Destroy(tok); -#endif + nssToken_Destroy(tok); } NSS_IMPLEMENT PRStatus @@ -135,6 +132,48 @@ NSSTrustDomain_Destroy return PR_SUCCESS; } +/* XXX uses tokens until slot list is in place */ +static NSSSlot ** +nssTrustDomain_GetActiveSlots +( + NSSTrustDomain *td, + nssUpdateLevel *updateLevel +) +{ + PRUint32 count; + NSSSlot **slots = NULL; + NSSToken **tp, **tokens; + *updateLevel = 1; + count = nssList_Count(td->tokenList); + tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1); + if (!tokens) { + return NULL; + } + slots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1); + if (!slots) { + nss_ZFreeIf(tokens); + return NULL; + } + nssList_GetArray(td->tokenList, (void **)tokens, count); + count = 0; + for (tp = tokens; *tp; tp++) { + slots[count++] = nssToken_GetSlot(*tp); + } + nss_ZFreeIf(tokens); + return slots; +} + +/* XXX */ +static nssSession * +nssTrustDomain_GetSessionForToken +( + NSSTrustDomain *td, + NSSToken *token +) +{ + return nssToken_GetDefaultSession(token); +} + NSS_IMPLEMENT PRStatus NSSTrustDomain_SetDefaultCallback ( @@ -143,8 +182,24 @@ NSSTrustDomain_SetDefaultCallback NSSCallback **oldCallbackOpt ) { - nss_SetError(NSS_ERROR_NOT_FOUND); - return PR_FAILURE; + if (oldCallbackOpt) { + *oldCallbackOpt = td->defaultCallback; + } + td->defaultCallback = newCallback; + return PR_SUCCESS; +} + +NSS_IMPLEMENT NSSCallback * +nssTrustDomain_GetDefaultCallback +( + NSSTrustDomain *td, + PRStatus *statusOpt +) +{ + if (statusOpt) { + *statusOpt = PR_SUCCESS; + } + return td->defaultCallback; } NSS_IMPLEMENT NSSCallback * @@ -154,8 +209,7 @@ NSSTrustDomain_GetDefaultCallback PRStatus *statusOpt ) { - nss_SetError(NSS_ERROR_NOT_FOUND); - return NULL; + return nssTrustDomain_GetDefaultCallback(td, statusOpt); } NSS_IMPLEMENT PRStatus @@ -231,8 +285,10 @@ NSSTrustDomain_FindTokenByName tok != (NSSToken *)NULL; tok = (NSSToken *)nssListIterator_Next(td->tokens)) { - myName = nssToken_GetName(tok); - if (nssUTF8_Equal(tokenName, myName, &nssrv)) break; + if (nssToken_IsPresent(tok)) { + myName = nssToken_GetName(tok); + if (nssUTF8_Equal(tokenName, myName, &nssrv)) break; + } } nssListIterator_Finish(td->tokens); return tok; @@ -366,83 +422,115 @@ NSSTrustDomain_ImportEncodedPublicKey return NULL; } -static void cert_destructor(void *el) +static NSSCertificate ** +get_certs_from_list(nssList *list) { - NSSCertificate *c = (NSSCertificate *)el; - NSSCertificate_Destroy(c); -} - -struct collect_arg_str { - nssList *list; - PRUint32 maximum; -}; - -extern const NSSError NSS_ERROR_MAXIMUM_FOUND; - -static PRStatus -collect_certs(NSSCertificate *c, void *arg) -{ - struct collect_arg_str *ca = (struct collect_arg_str *)arg; - /* Add the cert to the return list if not present */ - if (!nssList_Get(ca->list, (void *)c)) { - nssCertificate_AddRef(c); - nssList_Add(ca->list, (void *)c); - } - if (ca->maximum > 0 && nssList_Count(ca->list) >= ca->maximum) { - /* signal the end of collection) */ - nss_SetError(NSS_ERROR_MAXIMUM_FOUND); - return PR_FAILURE; + PRUint32 count = nssList_Count(list); + NSSCertificate **certs = NULL; + if (count > 0) { + certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); + if (certs) { + nssList_GetArray(list, (void **)certs, count); + } } - return PR_SUCCESS; + return certs; } -NSS_IMPLEMENT NSSCertificate * -NSSTrustDomain_FindBestCertificateByNickname +NSS_IMPLEMENT NSSCertificate ** +nssTrustDomain_FindCertificatesByNickname ( NSSTrustDomain *td, NSSUTF8 *name, - NSSTime *timeOpt, /* NULL for "now" */ - NSSUsage *usage, - NSSPolicies *policiesOpt /* NULL for none */ + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt ) { - PRStatus nssrv; - NSSToken *token; - nssTokenCertSearch search; - nssBestCertificateCB best; + PRStatus status; + PRUint32 numRemaining; + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; + NSSCertificate **rvCerts = NULL; + nssPKIObjectCollection *collection = NULL; + nssUpdateLevel updateLevel; nssList *nameList; - PRBool notPresent; - /* set the criteria for determining the best cert */ - nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt); - /* find all matching certs in the cache */ + /* First, grab from the cache */ nameList = nssList_Create(NULL, PR_FALSE); + if (!nameList) { + return NULL; + } (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList); - /* set the search criteria */ - search.callback = nssBestCertificate_Callback; - search.cbarg = &best; - search.cached = nameList; - search.searchType = nssTokenSearchType_TokenOnly; - /* traverse the tokens */ - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - if (nssToken_SearchCerts(token, ¬Present)) { - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - name, &search); - } - if (notPresent) { - nssCertificateList_DestroyTokenCerts(nameList, token); + rvCerts = get_certs_from_list(nameList); + /* initialize the collection of token certificates with the set of + * cached certs (if any). + */ + collection = nssCertificateCollection_Create(td, rvCerts); + nssCertificateArray_Destroy(rvCerts); + nssList_Destroy(nameList); + if (!collection) { + return (NSSCertificate **)NULL; + } + /* obtain the current set of active slots in the trust domain */ + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + /* iterate over the slots */ + numRemaining = maximumOpt; + for (slotp = slots; *slotp; slotp++) { + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssCryptokiObject **instances; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + session = nssTrustDomain_GetSessionForToken(td, token); + if (!session) { + nssToken_Destroy(token); + goto loser; + } + instances = nssToken_FindCertificatesByNickname(token, + session, + name, + tokenOnly, + numRemaining, + &status); + nssToken_Destroy(token); + if (status != PR_SUCCESS) { + goto loser; + } + if (instances) { + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + nss_ZFreeIf(instances); + if (status != PR_SUCCESS) { + goto loser; + } + if (maximumOpt > 0) { + PRUint32 count; + count = nssPKIObjectCollection_Count(collection); + numRemaining = maximumOpt - count; + if (numRemaining == 0) break; + } + } } } - nssListIterator_Finish(td->tokens); - nssCertificateList_DoCallback(nameList, nssBestCertificate_Callback, &best); - nssList_Clear(nameList, cert_destructor); - nssList_Destroy(nameList); - if (best.cert) { - nssTrustDomain_AddCertsToCache(td, &best.cert, 1); + /* Grab the certs collected in the search. */ + rvCerts = nssPKIObjectCollection_GetCertificates(collection, + rvOpt, maximumOpt, + arenaOpt); + /* clean up */ + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return rvCerts; +loser: + if (slots) { + nssSlotArray_Destroy(slots); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); } - return best.cert; + return (NSSCertificate **)NULL; } NSS_IMPLEMENT NSSCertificate ** @@ -455,260 +543,204 @@ NSSTrustDomain_FindCertificatesByNickname NSSArena *arenaOpt ) { - NSSCertificate **rvCerts = NULL; - NSSToken *token; - PRUint32 count; - PRStatus nssrv; - nssList *nameList; - nssTokenCertSearch search; - struct collect_arg_str ca; - PRBool notPresent; - /* set up the collection */ - nameList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList); - ca.list = nameList; - ca.maximum = maximumOpt; - /* set the search criteria */ - search.callback = collect_certs; - search.cbarg = &ca; - search.cached = nameList; - search.searchType = nssTokenSearchType_TokenOnly; - /* traverse the tokens */ - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - if (nssToken_SearchCerts(token, ¬Present)) { - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - name, &search); - } - if (notPresent) { - nssCertificateList_DestroyTokenCerts(nameList, token); - } - } - nssListIterator_Finish(td->tokens); - count = nssList_Count(nameList); - if (maximumOpt > 0 && count > maximumOpt) count = maximumOpt; - if (count > 0) { - if (rvOpt) { - nssList_GetArray(nameList, (void **)rvOpt, count); - rvOpt[count] = NULL; - } else { - rvCerts = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, count + 1); - nssList_GetArray(nameList, (void **)rvCerts, count); - } - nssTrustDomain_AddCertsToCache(td, rvCerts, count); - } - nssList_Destroy(nameList); - /* The return array assumes the references from the list */ - return rvCerts; -} - -static PRBool cert_token_not_present(NSSCertificate *c) -{ - nssListIterator *instances; - nssCryptokiInstance *instance; - PRBool freeIt = PR_FALSE; - PRBool notPresent = PR_TRUE; - instances = nssList_CreateIterator(c->object.instanceList); - for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); - instance != (nssCryptokiInstance *)NULL; - instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) - { - if (!nssToken_IsPresent(instance->token)) { - nssToken_DestroyCertList(instance->token, PR_TRUE); - nssList_Remove(c->object.instanceList, instance); - freeIt = PR_TRUE; - } else { - notPresent = PR_FALSE; - } - } - nssListIterator_Finish(instances); - nssListIterator_Destroy(instances); - if (freeIt) { - nssListIterator_Destroy(c->object.instances); - c->object.instances = nssList_CreateIterator(c->object.instanceList); - } - return notPresent; + return nssTrustDomain_FindCertificatesByNickname(td, + name, + rvOpt, + maximumOpt, + arenaOpt); } NSS_IMPLEMENT NSSCertificate * -NSSTrustDomain_FindCertificateByIssuerAndSerialNumber +nssTrustDomain_FindBestCertificateByNickname ( NSSTrustDomain *td, - NSSDER *issuer, - NSSDER *serialNumber + NSSUTF8 *name, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt ) { + NSSCertificate **nicknameCerts; NSSCertificate *rvCert = NULL; - NSSToken *tok; - /* Try the cache */ - rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td, - issuer, - serialNumber); - if (rvCert) { - if (cert_token_not_present(rvCert)) { - CERT_DestroyCertificate(STAN_GetCERTCertificate(rvCert)); - rvCert = NULL; - } - return rvCert; - } - /* Not cached, look for it on tokens */ - for (tok = (NSSToken *)nssListIterator_Start(td->tokens); - tok != (NSSToken *)NULL; - tok = (NSSToken *)nssListIterator_Next(td->tokens)) - { - if (nssToken_SearchCerts(tok, NULL)) { - rvCert = nssToken_FindCertificateByIssuerAndSerialNumber(tok, - NULL, - issuer, - serialNumber, - nssTokenSearchType_TokenOnly); - } -#ifdef NSS_3_4_CODE - if (!rvCert) { - /* Some tokens expect a decoded serial number. For compatibility, - * try the search again. - */ - NSSDER decodedSerial; - SECItem ds = { 0 }; - SECItem sn; - SECStatus secrv; - sn.data = serialNumber->data; - sn.len = serialNumber->size; - secrv = SEC_ASN1DecodeItem(NULL, &ds, SEC_IntegerTemplate, &sn); - if (secrv == SECSuccess) { - decodedSerial.data = ds.data; - decodedSerial.size = ds.len; - if (nssToken_SearchCerts(tok, NULL)) { - rvCert = nssToken_FindCertificateByIssuerAndSerialNumber( - tok, - NULL, - issuer, - &decodedSerial, - nssTokenSearchType_TokenOnly); - } - PORT_Free(ds.data); - } - } -#endif - if (rvCert) { - /* cache it */ - nssTrustDomain_AddCertsToCache(td, &rvCert, 1); - break; - } + nicknameCerts = nssTrustDomain_FindCertificatesByNickname(td, name, + NULL, + 0, + NULL); + if (nicknameCerts) { + rvCert = nssCertificateArray_FindBestCertificate(nicknameCerts, + timeOpt, + usage, + policiesOpt); + nssCertificateArray_Destroy(nicknameCerts); } - nssListIterator_Finish(td->tokens); return rvCert; } NSS_IMPLEMENT NSSCertificate * -NSSTrustDomain_FindBestCertificateBySubject +NSSTrustDomain_FindBestCertificateByNickname ( NSSTrustDomain *td, - NSSDER *subject, + NSSUTF8 *name, NSSTime *timeOpt, NSSUsage *usage, NSSPolicies *policiesOpt ) { - PRStatus nssrv; - NSSToken *token; - nssList *subjectList; - nssBestCertificateCB best; - nssTokenCertSearch search; - PRBool notPresent; - /* set the criteria for determining the best cert */ - nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt); - /* find all matching certs in the cache */ - subjectList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList); - /* set the search criteria */ - search.callback = nssBestCertificate_Callback; - search.cbarg = &best; - search.cached = subjectList; - search.searchType = nssTokenSearchType_TokenOnly; - /* traverse the tokens */ - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - if (nssToken_SearchCerts(token, ¬Present)) { - nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, - subject, &search); - } - if (notPresent) { - nssCertificateList_DestroyTokenCerts(subjectList, token); - } - } - nssListIterator_Finish(td->tokens); - nssCertificateList_DoCallback(subjectList, - nssBestCertificate_Callback, &best); - nssList_Clear(subjectList, cert_destructor); - nssList_Destroy(subjectList); - if (best.cert) { - nssTrustDomain_AddCertsToCache(td, &best.cert, 1); - } - return best.cert; + return nssTrustDomain_FindBestCertificateByNickname(td, + name, + timeOpt, + usage, + policiesOpt); } NSS_IMPLEMENT NSSCertificate ** -NSSTrustDomain_FindCertificatesBySubject +nssTrustDomain_FindCertificatesBySubject ( NSSTrustDomain *td, NSSDER *subject, NSSCertificate *rvOpt[], - PRUint32 maximumOpt, /* 0 for no max */ + PRUint32 maximumOpt, NSSArena *arenaOpt ) { - PRStatus nssrv; + PRStatus status; + PRUint32 numRemaining; + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; NSSCertificate **rvCerts = NULL; - NSSToken *token; - PRUint32 count; + nssPKIObjectCollection *collection = NULL; + nssUpdateLevel updateLevel; nssList *subjectList; - struct collect_arg_str ca; - nssTokenCertSearch search; - PRBool notPresent; - /* set up the collection */ + /* look in cache */ subjectList = nssList_Create(NULL, PR_FALSE); + if (!subjectList) { + return NULL; + } (void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList); - ca.list = subjectList; - ca.maximum = maximumOpt; - /* set the search criteria */ - search.callback = collect_certs; - search.cbarg = &ca; - search.cached = subjectList; - search.searchType = nssTokenSearchType_TokenOnly; - /* traverse the tokens */ - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - if (nssToken_SearchCerts(token, ¬Present)) { - nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, - subject, &search); - } - if (notPresent) { - nssCertificateList_DestroyTokenCerts(subjectList, token); - } + rvCerts = get_certs_from_list(subjectList); + collection = nssCertificateCollection_Create(td, rvCerts); + nssCertificateArray_Destroy(rvCerts); + nssList_Destroy(subjectList); + if (!collection) { + return (NSSCertificate **)NULL; } - nssListIterator_Finish(td->tokens); - count = nssList_Count(subjectList); - if (maximumOpt > 0 && count > maximumOpt) count = maximumOpt; - if (count > 0) { - if (rvOpt) { - nssList_GetArray(subjectList, (void **)rvOpt, count); - rvOpt[count] = NULL; - } else { - rvCerts = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, count + 1); - nssList_GetArray(subjectList, (void **)rvCerts, count); + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + numRemaining = maximumOpt; + for (slotp = slots; *slotp; slotp++) { + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssCryptokiObject **instances; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + session = nssTrustDomain_GetSessionForToken(td, token); + if (!session) { + nssToken_Destroy(token); + goto loser; + } + instances = nssToken_FindCertificatesBySubject(token, + session, + subject, + tokenOnly, + numRemaining, + &status); + nssToken_Destroy(token); + if (status != PR_SUCCESS) { + goto loser; + } + if (instances) { + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + nss_ZFreeIf(instances); + if (status != PR_SUCCESS) { + goto loser; + } + if (maximumOpt > 0) { + PRUint32 count; + count = nssPKIObjectCollection_Count(collection); + numRemaining = maximumOpt - count; + if (numRemaining == 0) break; + } + } } - nssTrustDomain_AddCertsToCache(td, rvCerts, count); } - nssList_Destroy(subjectList); - /* The return array assumes the references from the list */ + rvCerts = nssPKIObjectCollection_GetCertificates(collection, + rvOpt, maximumOpt, + arenaOpt); + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); return rvCerts; +loser: + if (slots) { + nssSlotArray_Destroy(slots); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + return (NSSCertificate **)NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindCertificatesBySubject +( + NSSTrustDomain *td, + NSSDER *subject, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, + NSSArena *arenaOpt +) +{ + return nssTrustDomain_FindCertificatesBySubject(td, + subject, + rvOpt, + maximumOpt, + arenaOpt); +} + +NSS_IMPLEMENT NSSCertificate * +nssTrustDomain_FindBestCertificateBySubject +( + NSSTrustDomain *td, + NSSDER *subject, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt +) +{ + NSSCertificate **subjectCerts; + NSSCertificate *rvCert = NULL; + subjectCerts = nssTrustDomain_FindCertificatesBySubject(td, subject, + NULL, + 0, + NULL); + if (subjectCerts) { + rvCert = nssCertificateArray_FindBestCertificate(subjectCerts, + timeOpt, + usage, + policiesOpt); + nssCertificateArray_Destroy(subjectCerts); + } + return rvCert; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestCertificateBySubject +( + NSSTrustDomain *td, + NSSDER *subject, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt +) +{ + return nssTrustDomain_FindBestCertificateBySubject(td, + subject, + timeOpt, + usage, + policiesOpt); } NSS_IMPLEMENT NSSCertificate * @@ -740,45 +772,138 @@ NSSTrustDomain_FindCertificatesByNameComponents } NSS_IMPLEMENT NSSCertificate * -NSSTrustDomain_FindCertificateByEncodedCertificate +nssTrustDomain_FindCertificateByIssuerAndSerialNumber ( NSSTrustDomain *td, - NSSBER *encodedCertificate + NSSDER *issuer, + NSSDER *serial ) { + PRStatus status; + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; NSSCertificate *rvCert = NULL; - NSSToken *tok; - /* Try the cache */ - rvCert = nssTrustDomain_GetCertByDERFromCache(td, encodedCertificate); + nssPKIObjectCollection *collection = NULL; + nssUpdateLevel updateLevel; + /* see if this search is already cached */ + rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td, + issuer, + serial); if (rvCert) { - if (cert_token_not_present(rvCert)) { - CERT_DestroyCertificate(STAN_GetCERTCertificate(rvCert)); - rvCert = NULL; - } return rvCert; } - /* Not cached, look for it on tokens */ - for (tok = (NSSToken *)nssListIterator_Start(td->tokens); - tok != (NSSToken *)NULL; - tok = (NSSToken *)nssListIterator_Next(td->tokens)) - { - if (nssToken_SearchCerts(tok, NULL)) { - rvCert = nssToken_FindCertificateByEncodedCertificate(tok, NULL, - encodedCertificate, - nssTokenSearchType_TokenOnly); + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + for (slotp = slots; *slotp; slotp++) { + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssCryptokiObject *instance; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + session = nssTrustDomain_GetSessionForToken(td, token); + if (!session) { + nssToken_Destroy(token); + goto loser; + } + instance = nssToken_FindCertificateByIssuerAndSerialNumber( + token, + session, + issuer, + serial, + tokenOnly, + &status); + nssToken_Destroy(token); + if (status != PR_SUCCESS) { + goto loser; + } + if (instance) { + if (!collection) { + collection = nssCertificateCollection_Create(td, NULL); + if (!collection) { + goto loser; + } + } + nssPKIObjectCollection_AddInstances(collection, + &instance, 1); + } } - if (rvCert) { - /* cache it */ - nssTrustDomain_AddCertsToCache(td, &rvCert, 1); - break; + } + if (collection) { + (void)nssPKIObjectCollection_GetCertificates(collection, + &rvCert, 1, NULL); + nssPKIObjectCollection_Destroy(collection); + if (!rvCert) { + goto loser; } } - nssListIterator_Finish(td->tokens); + nssSlotArray_Destroy(slots); + return rvCert; +loser: + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + if (slots) { + nssSlotArray_Destroy(slots); + } + return (NSSCertificate *)NULL; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindCertificateByIssuerAndSerialNumber +( + NSSTrustDomain *td, + NSSDER *issuer, + NSSDER *serial +) +{ + return nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td, + issuer, + serial); +} + +NSS_IMPLEMENT NSSCertificate * +nssTrustDomain_FindCertificateByEncodedCertificate +( + NSSTrustDomain *td, + NSSBER *ber +) +{ + PRStatus status; + NSSCertificate *rvCert = NULL; + NSSDER issuer = { 0 }; + NSSDER serial = { 0 }; + NSSArena *arena = nssArena_Create(); + if (!arena) { + return (NSSCertificate *)NULL; + } + /* XXX this is not generic... will any cert crack into issuer/serial? */ + status = nssPKIX509_GetIssuerAndSerialFromDER(ber, arena, &issuer, &serial); + if (status != PR_SUCCESS) { + goto finish; + } + rvCert = nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td, + &issuer, + &serial); +finish: + nssArena_Destroy(arena); return rvCert; } NSS_IMPLEMENT NSSCertificate * -NSSTrustDomain_FindCertificateByEmail +NSSTrustDomain_FindCertificateByEncodedCertificate +( + NSSTrustDomain *td, + NSSBER *ber +) +{ + return nssTrustDomain_FindCertificateByEncodedCertificate(td, ber); +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestCertificateByEmail ( NSSTrustDomain *td, NSSASCII7 *email, @@ -787,44 +912,7 @@ NSSTrustDomain_FindCertificateByEmail NSSPolicies *policiesOpt ) { - PRStatus nssrv; - NSSToken *token; - nssBestCertificateCB best; - nssTokenCertSearch search; - nssList *emailList; - PRBool notPresent; - /* set the criteria for determining the best cert */ - nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt); - /* find all matching certs in the cache */ - emailList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForEmailAddressFromCache(td, email, emailList); - /* set the search criteria */ - search.callback = nssBestCertificate_Callback; - search.cbarg = &best; - search.cached = emailList; - search.searchType = nssTokenSearchType_TokenOnly; - /* traverse the tokens */ - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - if (nssToken_SearchCerts(token, ¬Present)) { - nssrv = nssToken_TraverseCertificatesByEmail(token, NULL, - email, &search); - } - if (notPresent) { - nssCertificateList_DestroyTokenCerts(emailList, token); - } - } - nssListIterator_Finish(td->tokens); - nssCertificateList_DoCallback(emailList, - nssBestCertificate_Callback, &best); - nssList_Clear(emailList, cert_destructor); - nssList_Destroy(emailList); - if (best.cert) { - nssTrustDomain_AddCertsToCache(td, &best.cert, 1); - } - return best.cert; + return 0; } NSS_IMPLEMENT NSSCertificate ** @@ -947,127 +1035,309 @@ NSSTrustDomain_FindUserCertificatesForEmailSigning return NULL; } -struct traverse_arg +static PRStatus +collector(nssCryptokiObject *instance, void *arg) { - PRStatus (*callback)(NSSCertificate *c, void *arg); - nssList *cached; - void *arg; -}; + nssPKIObjectCollection *collection = (nssPKIObjectCollection *)arg; + return nssPKIObjectCollection_AddInstanceAsObject(collection, instance); +} -static PRStatus traverse_callback(NSSCertificate *c, void *arg) +NSS_IMPLEMENT PRStatus * +NSSTrustDomain_TraverseCertificates +( + NSSTrustDomain *td, + PRStatus (*callback)(NSSCertificate *c, void *arg), + void *arg +) { - PRStatus nssrv; - struct traverse_arg *ta = (struct traverse_arg *)arg; - NSSCertificate *cp = nssCertificate_AddRef(c); - NSSTrustDomain *td = NSSCertificate_GetTrustDomain(c); - /* The cert coming in has been retrieved from a token. It was not in - * the cache when the search was begun. But it may be in the cache now, - * and if it isn't, it will be, because it is going to be cracked into - * a CERTCertificate and fed into the callback. - */ - nssrv = nssTrustDomain_AddCertsToCache(td, &c, 1); - if (!nssList_Get(ta->cached, c)) { - /* add it to the cached list for this search */ - nssCertificate_AddRef(c); - nssList_Add(ta->cached, c); + PRStatus status; + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; + nssPKIObjectCollection *collection = NULL; + nssPKIObjectCallback pkiCallback; + nssUpdateLevel updateLevel; + NSSCertificate **cached = NULL; + nssList *certList; + + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) return NULL; + (void *)nssTrustDomain_GetCertsFromCache(td, certList); + cached = get_certs_from_list(certList); + collection = nssCertificateCollection_Create(td, cached); + nssCertificateArray_Destroy(cached); + nssList_Destroy(certList); + if (!collection) { + return (PRStatus *)NULL; + } + /* obtain the current set of active slots in the trust domain */ + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + /* iterate over the slots */ + for (slotp = slots; *slotp; slotp++) { + /* get the token for the slot, if present */ + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + /* get a session for the token */ + session = nssTrustDomain_GetSessionForToken(td, token); + if (!session) { + nssToken_Destroy(token); + goto loser; + } + /* perform the traversal */ + status = nssToken_TraverseCertificates(token, + session, + tokenOnly, + collector, + collection); + nssToken_Destroy(token); + if (status != PR_SUCCESS) { + goto loser; + } + } } - /* This is why the hack of copying the cert was done above. The pointer - * c passed to this function is provided by retrieve_cert. That function - * will destroy the pointer once this function returns. Since c is a local - * copy, there is no way to notify retrieve_cert if it has changed. That - * would happen if the above call to add it to the cache found the cert - * already there. In that case, the pointer c passed to the callback - * below will be the cached cert, and the pointer c that retrieve_cert - * has will be the same as the copy made above. Thus, retrieve_cert will - * destroy the reference to the copy, the callback will use the reference - * to the cached entry, and everyone should be happy. - */ - nssrv = (*ta->callback)(c, ta->arg); - /* This function owns a reference to the cert, either from the AddRef - * or by getting it from the cache. - */ - CERT_DestroyCertificate(STAN_GetCERTCertificate(c)); - return nssrv; -} -#ifdef NSS_3_4_CODE -static void cert_destructor_with_cache(void *el) -{ - NSSCertificate *c = (NSSCertificate *)el; - CERTCertificate *cert = STAN_GetCERTCertificate(c); - /* It's already been obtained as a CERTCertificate, so it must - * be destroyed as one - */ - CERT_DestroyCertificate(cert); + /* Traverse the collection */ + pkiCallback.func.cert = callback; + pkiCallback.arg = arg; + status = nssPKIObjectCollection_Traverse(collection, &pkiCallback); + /* clean up */ + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return NULL; +loser: + if (slots) { + nssSlotArray_Destroy(slots); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + return NULL; } -#endif +#ifdef notdef +/* + * search for Public and Private keys first + */ NSS_IMPLEMENT PRStatus * -NSSTrustDomain_TraverseCertificates +NSSTrustDomain_TraverseUserCertificates ( NSSTrustDomain *td, PRStatus (*callback)(NSSCertificate *c, void *arg), void *arg ) { - PRStatus nssrv; - NSSToken *token; - nssList *certList, *cacheList; - nssTokenCertSearch search; - struct traverse_arg ta; - nssListIterator *tokens; - PRBool notPresent; + PRStatus status; + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; + nssPKIObjectCollection *collection = NULL; + nssPKIObjectCallback pkiCallback; + nssUpdateLevel updateLevel; + NSSCertificate **cached = NULL; + nssList *certList; certList = nssList_Create(NULL, PR_FALSE); if (!certList) return NULL; (void *)nssTrustDomain_GetCertsFromCache(td, certList); - cacheList = nssList_Clone(certList); - if (!cacheList) { - goto cleanup; + cached = get_certs_from_list(certList); + collection = nssCertificateCollection_Create(td, cached); + nssCertificateArray_Destroy(cached); + nssList_Destroy(certList); + if (!collection) { + return (PRStatus *)NULL; } - /* set traverse args */ - ta.callback = callback; - ta.cached = certList; - ta.arg = arg; - /* set the search criteria */ - search.callback = traverse_callback; - search.cbarg = &ta; - search.cached = certList; - search.searchType = nssTokenSearchType_TokenOnly; - /* Must create a local copy of the token list, because the callback - * above may want to traverse the tokens as well. - */ - tokens = nssList_CreateIterator(td->tokenList); - if (!tokens) { - goto cleanup; + /* obtain the current set of active slots in the trust domain */ + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; } - /* traverse the tokens */ - for (token = (NSSToken *)nssListIterator_Start(tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(tokens)) - { - if (nssToken_SearchCerts(token, ¬Present)) { - nssrv = nssToken_TraverseCertificates(token, NULL, &search); - } - if (notPresent) { - nssCertificateList_RemoveTokenCerts(cacheList, token); + /* iterate over the slots */ + for (slotp = slots; *slotp; slotp++) { + /* get the token for the slot, if present */ + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssCryptokiObject **instances; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + /* get a session for the token */ + session = nssTrustDomain_GetSessionForToken(td, token); + if (!session) { + nssToken_Destroy(token); + goto loser; + } + /* perform the traversal */ + if (!isLoggedIn(tok)) { + instances = nssToken_FindPublicKeys(token, + session, + tokenOnly, + 0, &status); + } else { + instances = nssToken_FindPrivateKeys(token, + session, + tokenOnly, + 0, &status); + } + nssToken_Destroy(token); + if (status != PR_SUCCESS) { + goto loser; + } + /* add the found certificates to the collection */ + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + nss_ZFreeIf(instances); + if (status != PR_SUCCESS) { + goto loser; + } } } - nssListIterator_Finish(tokens); - nssListIterator_Destroy(tokens); - /* now do the callback on the cached certs, - * sans certs from removed tokens - */ - nssCertificateList_DoCallback(cacheList, callback, arg); - nssList_Destroy(cacheList); -cleanup: -#ifdef NSS_3_4_CODE - nssList_Clear(certList, cert_destructor_with_cache); -#else - nssList_Clear(certList, cert_destructor); -#endif - nssList_Destroy(certList); + status = nssPKIObjectCollection_MatchCerts(collection); + if (status != PR_SUCCESS) { + goto loser; + } + /* Traverse the collection */ + pkiCallback.func.cert = callback; + pkiCallback.arg = arg; + status = nssPKIObjectCollection_Traverse(collection, &pkiCallback); + /* clean up */ + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return NULL; +loser: + if (slots) { + nssSlotArray_Destroy(slots); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } return NULL; } +#endif + +NSS_IMPLEMENT NSSTrust * +nssTrustDomain_FindTrustForCertificate +( + NSSTrustDomain *td, + NSSCertificate *c +) +{ + PRStatus status; + NSSSlot **slots; + NSSSlot **slotp; + NSSToken *token; + nssCryptokiObject *to = NULL; + nssPKIObject *pkio = NULL; + NSSTrust *rvt = NULL; + nssUpdateLevel updateLevel; + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + return (NSSTrust *)NULL; + } + for (slotp = slots; *slotp; slotp++) { + token = nssSlot_GetToken(*slotp); + if (token) { + to = nssToken_FindTrustForCertificate(token, NULL, + &c->encoding, + &c->issuer, + &c->serial, + nssTokenSearchType_TokenOnly); + if (to) { + if (!pkio) { + pkio = nssPKIObject_Create(NULL, to, td, NULL); + if (!pkio) { + goto loser; + } + } else { + status = nssPKIObject_AddInstance(pkio, to); + if (status != PR_SUCCESS) { + goto loser; + } + } + } + nssToken_Destroy(token); + } + } + if (pkio) { + rvt = nssTrust_Create(pkio); + if (!rvt) { + goto loser; + } + } + nssSlotArray_Destroy(slots); + return rvt; +loser: + nssSlotArray_Destroy(slots); + if (to) { + nssCryptokiObject_Destroy(to); + } + if (pkio) { + nssPKIObject_Destroy(pkio); + } + return (NSSTrust *)NULL; +} + +NSS_IMPLEMENT NSSCRL ** +nssTrustDomain_FindCRLsBySubject +( + NSSTrustDomain *td, + NSSDER *subject +) +{ + PRStatus status; + NSSSlot **slots; + NSSSlot **slotp; + NSSToken *token; + nssUpdateLevel updateLevel; + nssPKIObjectCollection *collection; + NSSCRL **rvCRLs = NULL; + collection = nssCRLCollection_Create(td, NULL); + if (!collection) { + return (NSSCRL **)NULL; + } + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + for (slotp = slots; *slotp; slotp++) { + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssCryptokiObject **instances; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + /* get a session for the token */ + session = nssTrustDomain_GetSessionForToken(td, token); + if (!session) { + nssToken_Destroy(token); + goto loser; + } + /* perform the traversal */ + instances = nssToken_FindCRLsBySubject(token, session, subject, + tokenOnly, 0, &status); + nssToken_Destroy(token); + if (status != PR_SUCCESS) { + goto loser; + } + /* add the found CRL's to the collection */ + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + nss_ZFreeIf(instances); + if (status != PR_SUCCESS) { + goto loser; + } + } + } + rvCRLs = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return rvCRLs; +loser: + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return (NSSCRL **)NULL; +} NSS_IMPLEMENT PRStatus NSSTrustDomain_GenerateKeyPair @@ -1127,25 +1397,23 @@ NSSTrustDomain_FindSymmetricKeyByAlgorithmAndKeyID } NSS_IMPLEMENT NSSCryptoContext * +nssTrustDomain_CreateCryptoContext +( + NSSTrustDomain *td, + NSSCallback *uhhOpt +) +{ + return nssCryptoContext_Create(td, uhhOpt); +} + +NSS_IMPLEMENT NSSCryptoContext * NSSTrustDomain_CreateCryptoContext ( NSSTrustDomain *td, NSSCallback *uhhOpt ) { - NSSArena *arena; - NSSCryptoContext *rvCC; - arena = NSSArena_Create(); - if (!arena) { - return NULL; - } - rvCC = nss_ZNEW(arena, NSSCryptoContext); - if (!rvCC) { - return NULL; - } - rvCC->td = td; - rvCC->arena = arena; - return rvCC; + return nssTrustDomain_CreateCryptoContext(td, uhhOpt); } NSS_IMPLEMENT NSSCryptoContext * diff --git a/security/nss/lib/smime/cmscinfo.c b/security/nss/lib/smime/cmscinfo.c index 9e4a2dc5e..85756a536 100644 --- a/security/nss/lib/smime/cmscinfo.c +++ b/security/nss/lib/smime/cmscinfo.c @@ -78,6 +78,11 @@ NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo) } if (cinfo->bulkkey) PK11_FreeSymKey(cinfo->bulkkey); + + if (cinfo->ciphcx) { + NSS_CMSCipherContext_Destroy(cinfo->ciphcx); + cinfo->ciphcx = NULL; + } /* we live in a pool, so no need to worry about storage */ } diff --git a/security/nss/lib/smime/cmsencdata.c b/security/nss/lib/smime/cmsencdata.c index 61aae96d8..fdfa0a2b9 100644 --- a/security/nss/lib/smime/cmsencdata.c +++ b/security/nss/lib/smime/cmsencdata.c @@ -202,8 +202,10 @@ NSS_CMSEncryptedData_Encode_BeforeData(NSSCMSEncryptedData *encd) SECStatus NSS_CMSEncryptedData_Encode_AfterData(NSSCMSEncryptedData *encd) { - if (encd->contentInfo.ciphcx) + if (encd->contentInfo.ciphcx) { NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx); + encd->contentInfo.ciphcx = NULL; + } /* nothing to do after data */ return SECSuccess; @@ -265,7 +267,10 @@ loser: SECStatus NSS_CMSEncryptedData_Decode_AfterData(NSSCMSEncryptedData *encd) { - NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx); + if (encd->contentInfo.ciphcx) { + NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx); + encd->contentInfo.ciphcx = NULL; + } return SECSuccess; } diff --git a/security/nss/lib/smime/cmssigdata.c b/security/nss/lib/smime/cmssigdata.c index fab7189f2..03a37cda1 100644 --- a/security/nss/lib/smime/cmssigdata.c +++ b/security/nss/lib/smime/cmssigdata.c @@ -540,7 +540,7 @@ NSS_CMSSignedData_VerifyCertsOnly(NSSCMSSignedData *sigd, count = NSS_CMSArray_Count((void**)sigd->rawCerts); for (i=0; i < count; i++) { if (sigd->certs && sigd->certs[i]) { - cert = sigd->certs[i]; + cert = CERT_DupCertificate(sigd->certs[i]); } else { cert = CERT_FindCertByDERCert(certdb, sigd->rawCerts[i]); if (!cert) { @@ -550,6 +550,7 @@ NSS_CMSSignedData_VerifyCertsOnly(NSSCMSSignedData *sigd, } rv |= CERT_VerifyCert(certdb, cert, PR_TRUE, usage, PR_Now(), NULL, NULL); + CERT_DestroyCertificate(cert); } return rv; diff --git a/security/nss/lib/softoken/cdbhdl.h b/security/nss/lib/softoken/cdbhdl.h index b606e9876..f52712422 100644 --- a/security/nss/lib/softoken/cdbhdl.h +++ b/security/nss/lib/softoken/cdbhdl.h @@ -51,4 +51,21 @@ struct NSSLOWCERTCertDBHandleStr { PZMonitor *dbMon; }; +#ifdef DBM_USING_NSPR +#define NO_RDONLY PR_RDONLY +#define NO_RDWR PR_RDWR +#define NO_CREATE (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE) +#else +#define NO_RDONLY O_RDONLY +#define NO_RDWR O_RDWR +#define NO_CREATE (O_RDWR | O_CREAT | O_TRUNC) +#endif + +typedef DB * (*rdbfunc)(const char *appName, const char *prefix, + const char *type, int flags); + +DB * rdbopen(const char *appName, const char *prefix, + const char *type, int flags); + +SECStatus db_Copy(DB *dest,DB *src); #endif diff --git a/security/nss/lib/softoken/config.mk b/security/nss/lib/softoken/config.mk index b59f0cf32..0d72934be 100644 --- a/security/nss/lib/softoken/config.mk +++ b/security/nss/lib/softoken/config.mk @@ -95,3 +95,7 @@ MKSHLIB += -R '$$ORIGIN' endif endif endif + +ifeq ($(OS_TARGET),WINCE) +DEFINES += -DDBM_USING_NSPR +endif diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c index 8fa73fef2..87098dc0a 100644 --- a/security/nss/lib/softoken/dbinit.c +++ b/security/nss/lib/softoken/dbinit.c @@ -102,6 +102,29 @@ pk11_keydb_name_cb(void *arg, int dbVersion) #define CKR_CERTDB_FAILED CKR_DEVICE_ERROR #define CKR_KEYDB_FAILED CKR_DEVICE_ERROR +const char * +pk11_EvaluateConfigDir(const char *configdir,char **appName) +{ + if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) { + char *cdir; + + *appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1); + if (*appName == NULL) { + return configdir; + } + cdir = *appName; + while (*cdir && *cdir != ':') { + cdir++; + } + if (*cdir == ':') { + *cdir = 0; + cdir++; + } + configdir = cdir; + } + return configdir; +} + static CK_RV pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly, NSSLOWCERTCertDBHandle **certdbPtr) @@ -110,11 +133,14 @@ pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly, CK_RV crv = CKR_CERTDB_FAILED; SECStatus rv; char * name = NULL; + char * appName = NULL; if (prefix == NULL) { prefix = ""; } + configdir = pk11_EvaluateConfigDir(configdir, &appName); + name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix); if (name == NULL) goto loser; @@ -123,7 +149,7 @@ pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly, goto loser; /* fix when we get the DB in */ - rv = nsslowcert_OpenCertDB(certdb, readOnly, + rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix, pk11_certdb_name_cb, (void *)name, PR_FALSE); if (rv == SECSuccess) { crv = CKR_OK; @@ -133,6 +159,7 @@ pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly, loser: if (certdb) PR_Free(certdb); if (name) PORT_Free(name); + if (appName) PORT_Free(appName); return crv; } @@ -142,15 +169,20 @@ pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly, { NSSLOWKEYDBHandle *keydb; char * name = NULL; + char * appName = NULL; if (prefix == NULL) { prefix = ""; } + configdir = pk11_EvaluateConfigDir(configdir, &appName); + name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix); if (name == NULL) return SECFailure; - keydb = nsslowkey_OpenKeyDB(readOnly, pk11_keydb_name_cb, (void *)name); + keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix, + pk11_keydb_name_cb, (void *)name); PORT_Free(name); + if (appName) PORT_Free(appName); if (keydb == NULL) return CKR_KEYDB_FAILED; *keydbPtr = keydb; @@ -222,3 +254,57 @@ pk11_DBShutdown(NSSLOWCERTCertDBHandle *certHandle, keyHandle= NULL; } } + +static rdbfunc pk11_rdbfunc; + +/* NOTE: SHLIB_SUFFIX is defined on the command line */ +#define RDBLIB "rdb."SHLIB_SUFFIX + +DB * rdbopen(const char *appName, const char *prefix, + const char *type, int flags) +{ + PRLibrary *lib; + DB *db; + + if (pk11_rdbfunc) { + db = (*pk11_rdbfunc)(appName,prefix,type,flags); + return db; + } + + /* + * try to open the library. + */ + lib = PR_LoadLibrary(RDBLIB); + + if (!lib) { + return NULL; + } + + /* get the entry point */ + pk11_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen"); + if (pk11_rdbfunc) { + return (*pk11_rdbfunc)(appName,prefix,type,flags); + } + + /* couldn't find the entry point, unload the library and fail */ + PR_UnloadLibrary(lib); + return NULL; +} + +SECStatus +db_Copy(DB *dest,DB *src) +{ + int ret; + DBT key,data; + ret = (*src->seq)(src, &key, &data, R_FIRST); + if (ret) { + return SECSuccess; + } + + do { + (void)(*dest->put)(dest,&key,&data, R_NOOVERWRITE); + } while ( (*src->seq)(src, &key, &data, R_NEXT) == 0); + (void)(*dest->sync)(dest,0); + + return SECSuccess; +} diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c index e3abfaf88..c33670451 100644 --- a/security/nss/lib/softoken/fipstokn.c +++ b/security/nss/lib/softoken/fipstokn.c @@ -164,11 +164,17 @@ CK_RV FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) { return CKR_OK; } +/* sigh global so pkcs11 can read it */ +PRBool nsf_init = PR_FALSE; /* FC_Initialize initializes the PKCS #11 library. */ CK_RV FC_Initialize(CK_VOID_PTR pReserved) { CK_RV crv; + if (nsf_init) { + return CKR_CRYPTOKI_ALREADY_INITIALIZED; + } + crv = nsc_CommonInitialize(pReserved, PR_TRUE); /* not an 'else' rv can be set by either PK11_LowInit or PK11_SlotInit*/ @@ -181,17 +187,24 @@ CK_RV FC_Initialize(CK_VOID_PTR pReserved) { crv = pk11_fipsPowerUpSelfTest(); if (crv != CKR_OK) { + nsc_CommonFinalize(NULL, PR_TRUE); fatalError = PR_TRUE; return crv; } + nsf_init = PR_TRUE; return CKR_OK; } /*FC_Finalize indicates that an application is done with the PKCS #11 library.*/ CK_RV FC_Finalize (CK_VOID_PTR pReserved) { - /* this should free up FIPS Slot */ - return NSC_Finalize (pReserved); + CK_RV crv; + if (!nsf_init) { + return CKR_OK; + } + crv = nsc_CommonFinalize (pReserved, PR_TRUE); + nsf_init = (PRBool) !(crv == CKR_OK); + return crv; } @@ -203,7 +216,8 @@ CK_RV FC_GetInfo(CK_INFO_PTR pInfo) { /* FC_GetSlotList obtains a list of slots in the system. */ CK_RV FC_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { - return NSC_GetSlotList(tokenPresent,pSlotList,pulCount); + return nsc_CommonGetSlotList(tokenPresent,pSlotList,pulCount, + NSC_FIPS_MODULE); } /* FC_GetSlotInfo obtains information about a particular slot in the system. */ diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index 818427a08..dc58a402d 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -47,6 +47,7 @@ #include "mcom_db.h" #include "lowpbe.h" #include "secerr.h" +#include "cdbhdl.h" #include "keydbi.h" @@ -546,13 +547,6 @@ keyDBFilenameCallback(void *arg, int dbVersion) return(PORT_Strdup((char *)arg)); } -NSSLOWKEYDBHandle * -nsslowkey_OpenKeyDBFilename(char *dbname, PRBool readOnly) -{ - return(nsslowkey_OpenKeyDB(readOnly, keyDBFilenameCallback, - (void *)dbname)); -} - static SECStatus ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, SECItem *oldpwitem, SECItem *newpwitem, @@ -592,148 +586,12 @@ nsslowkey_version(DB *db) return 255; } - if ( ret == 1 ) { + if ( ret >= 1 ) { return 0; } return *( (unsigned char *)versionData.data); } -#ifdef NSS_USE_KEY4_DB -nsslowkey_UpdateKey3DBPass1(NSSLOWKEYDBHandle *handle) -{ - SECStatus rv; - DBT checkKey; - DBT checkData; - DBT saltKey; - DBT saltData; - DBT key; - DBT data; - DBT newKey; - unsigned char buf[SHA1_LENGTH]; - unsigned char version; - SECItem *rc4key = NULL; - NSSLOWKEYDBKey *dbkey = NULL; - SECItem *oldSalt = NULL; - int ret; - SECItem checkitem; - - if ( handle->updatedb == NULL ) { - return(SECSuccess); - } - - /* - * check the version record - */ - version = nsslowkey_version(handle->updatedb); - if (version != 3) { - goto done; - } - - saltKey.data = SALT_STRING; - saltKey.size = sizeof(SALT_STRING) - 1; - - ret = (* handle->updatedb->get)(handle->updatedb, &saltKey, &saltData, 0); - if ( ret ) { - /* no salt in old db, so it is corrupted */ - goto done; - } - - oldSalt = decodeKeyDBGlobalSalt(&saltData); - if ( oldSalt == NULL ) { - /* bad salt in old db, so it is corrupted */ - goto done; - } - - /* - * look for a pw check entry - */ - checkKey.data = KEYDB_PW_CHECK_STRING; - checkKey.size = KEYDB_PW_CHECK_LEN; - - ret = (* handle->updatedb->get)(handle->updatedb, &checkKey, - &checkData, 0 ); - if (ret) { - checkKey.data = KEYDB_FAKE_PW_CHECK_STRING; - checkKey.size = KEYDB_FAKE_PW_CHECK_LEN; - ret = (* handle->updatedb->get)(handle->updatedb, &checkKey, - &checkData, 0 ); - if (ret) { - goto done; - } - } - - /* put global salt into the new database now */ - ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); - if ( ret ) { - goto done; - } - - if (checkKey.size == KEYDB_PW_CHECK_LEN) { - dbkey = decode_dbkey(&checkData, 3); - if ( dbkey == NULL ) { - goto done; - } - rv = put_dbkey(handle, &checkKey, dbkey, PR_FALSE); - ret = (rv != SECSuccess); - } else { - ret = (* handle->db->put)(handle->db, &checkKey, &checkData, 0); - } - if ( ret ) { - goto done; - } - - /* now traverse the database */ - ret = (* handle->updatedb->seq)(handle->updatedb, &key, &data, R_FIRST); - if ( ret ) { - goto done; - } - - do { - - /* skip version record */ - if ( data.size > 1 ) { - /* skip salt */ - if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) { - if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) { - continue; - } - } - /* skip pw check entry */ - if ( key.size == checkKey.size ) { - if ( PORT_Memcmp(key.data, checkKey.data, key.size) == 0 ) { - continue; - } - } - dbkey = decode_dbkey(&data, 3); - if ( dbkey == NULL ) { - continue; - } - SHA1_HashBuf(buf,key.data,key.size); - newKey.data = buf; - newKey.size = SHA1_LENGTH; - - rv = put_dbkey(handle, &newKey, dbkey, PR_FALSE); - - sec_destroy_dbkey(dbkey); - - } - } while ( (* handle->updatedb->seq)(handle->updatedb, &key, &data, - R_NEXT) == 0 ); - -done: - /* sync the database */ - ret = (* handle->db->sync)(handle->db, 0); - - (* handle->updatedb->close)(handle->updatedb); - handle->updatedb = NULL; - - if ( oldSalt ) { - SECITEM_FreeItem(oldSalt, PR_TRUE); - } - return(SECSuccess); -} -#endif - static PRBool seckey_HasAServerKey(DB *db) { @@ -973,11 +831,9 @@ done: return(SECSuccess); } - - - NSSLOWKEYDBHandle * -nsslowkey_OpenKeyDB(PRBool readOnly, NSSLOWKEYDBNameFunc namecb, void *cbarg) +nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, + NSSLOWKEYDBNameFunc namecb, void *cbarg) { NSSLOWKEYDBHandle *handle; int ret; @@ -991,12 +847,8 @@ nsslowkey_OpenKeyDB(PRBool readOnly, NSSLOWKEYDBNameFunc namecb, void *cbarg) PORT_SetError (SEC_ERROR_NO_MEMORY); return NULL; } - - if ( readOnly ) { - openflags = O_RDONLY; - } else { - openflags = O_RDWR; - } + + openflags = readOnly ? NO_RDONLY : NO_RDWR; dbname = (*namecb)(cbarg, NSSLOWKEY_DB_FILE_VERSION); if ( dbname == NULL ) { @@ -1005,8 +857,12 @@ nsslowkey_OpenKeyDB(PRBool readOnly, NSSLOWKEYDBNameFunc namecb, void *cbarg) handle->dbname = PORT_Strdup(dbname); handle->readOnly = readOnly; - - handle->db = dbopen( dbname, openflags, 0600, DB_HASH, 0 ); + + if (appName) { + handle->db = rdbopen( appName, prefix, "key", openflags); + } else { + handle->db = dbopen( dbname, openflags, 0600, DB_HASH, 0 ); + } /* check for correct version number */ if (handle->db != NULL) { @@ -1025,40 +881,31 @@ nsslowkey_OpenKeyDB(PRBool readOnly, NSSLOWKEYDBNameFunc namecb, void *cbarg) } newdb: - + /* if first open fails, try to create a new DB */ if ( handle->db == NULL ) { -#ifdef NSS_USE_KEY4_DB - char *dbname3 = (*namecb)(cbarg, 3); - - if ( readOnly ) { - if (dbname3 == NULL) { - goto loser; - } - handle->db = dbopen( dbname3, O_RDONLY, 0600, DB_HASH, 0 ); - PORT_Free(handle->dbname); - handle->dbname = dbname3; - dbname3 = NULL; - if (handle->db == NULL) { - goto loser; - } - handle->version = nsslowkey_version(handle->db); - if (handle->version != 3) { - /* bogus version number record, reset the database */ - (* handle->db->close)( handle->db ); - handle->db = NULL; - goto loser; - } - goto done; - } -#else if ( readOnly ) { goto loser; } -#endif - - handle->db = dbopen( dbname, - O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); + + if (appName) { + handle->db = rdbopen( appName, prefix, "key", NO_CREATE); + handle->updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 ); + if (handle->updatedb) { + handle->version = nsslowkey_version(handle->updatedb); + if (handle->version != NSSLOWKEY_DB_FILE_VERSION) { + (*handle->updatedb->close)(handle->updatedb); + handle->updatedb = NULL; + } else { + db_Copy(handle->db, handle->updatedb); + (*handle->updatedb->close)(handle->updatedb); + handle->updatedb = NULL; + goto done; + } + } + } else { + handle->db = dbopen( dbname, NO_CREATE, 0600, DB_HASH, 0 ); + } PORT_Free( dbname ); dbname = NULL; @@ -1072,28 +919,12 @@ newdb: if ( rv != SECSuccess ) { goto loser; } - -#ifdef NSS_USE_KEY4_DB - handle->updatedb = dbopen( dbname3, O_RDONLY, 0600, DB_HASH, 0 ); - PORT_Free(dbname3); - dbname3 = NULL; - if (handle->updatedb) { - /* - * copy the key data, all the real work happens in pass2 - */ - rv = nsslowkey_UpdateKey3DBPass1(handle); - if ( rv == SECSuccess ) { - updated = PR_TRUE; - } - goto skip_v2_db; - } -#endif /* NSS_USE_KEY4_DB */ /* * try to update from v2 db */ dbname = (*namecb)(cbarg, 2); if ( dbname != NULL ) { - handle->updatedb = dbopen( dbname, O_RDONLY, 0600, DB_HASH, 0 ); + handle->updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 ); PORT_Free( dbname ); dbname = NULL; @@ -1112,9 +943,6 @@ newdb: } -#ifdef NSS_USE_KEY4_DB -skip_v2_db: -#endif /* we are using the old salt if we updated from an old db */ if ( ! updated ) { rv = makeGlobalSalt(handle); @@ -1130,9 +958,8 @@ skip_v2_db: } } -#ifdef NSS_USE_KEY4_DB done: -#endif + handle->global_salt = GetKeyDBGlobalSalt(handle); if ( dbname ) PORT_Free( dbname ); @@ -2557,8 +2384,7 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle) } (* handle->db->close)(handle->db); - handle->db = dbopen( handle->dbname, - O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); + handle->db = dbopen( handle->dbname, NO_CREATE, 0600, DB_HASH, 0 ); if (handle->db == NULL) { /* set an error code */ return SECFailure; diff --git a/security/nss/lib/softoken/lowkeyi.h b/security/nss/lib/softoken/lowkeyi.h index ccece767e..e1af7b0d1 100644 --- a/security/nss/lib/softoken/lowkeyi.h +++ b/security/nss/lib/softoken/lowkeyi.h @@ -66,11 +66,11 @@ typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion); ** Open a key database. */ extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly, + const char *domain, + const char *prefix, NSSLOWKEYDBNameFunc namecb, void *cbarg); -extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDBFilename(char *filename, - PRBool readOnly); /* * Clear out all the keys in the existing database diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c index 51831b4db..c858e9719 100644 --- a/security/nss/lib/softoken/lowpbe.c +++ b/security/nss/lib/softoken/lowpbe.c @@ -867,7 +867,7 @@ sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, encrypt); if(ctxt != NULL) { - rv = ((encrypt != PR_TRUE) ? DES_Decrypt : DES_Encrypt)( + rv = (encrypt ? DES_Encrypt : DES_Decrypt)( ctxt, dest->data, &dest->len, dup_src->len + 64, dup_src->data, dup_src->len); @@ -947,7 +947,7 @@ sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy, NSS_RC2_CBC, key->len); if(ctxt != NULL) { - rv = ((encrypt != PR_TRUE) ? RC2_Decrypt : RC2_Encrypt)( + rv = (encrypt ? RC2_Encrypt: RC2_Decrypt)( ctxt, dest->data, &dest->len, dup_src->len + 64, dup_src->data, dup_src->len); @@ -1004,7 +1004,7 @@ sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op, ctxt = RC4_CreateContext(key->data, key->len); if(ctxt) { - rv = ((encrypt != PR_FALSE) ? RC4_Decrypt : RC4_Encrypt)( + rv = (encrypt ? RC4_Encrypt : RC4_Decrypt)( ctxt, dest->data, &dest->len, src->len + 64, src->data, src->len); RC4_DestroyContext(ctxt, PR_TRUE); diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index 59da34782..1649cd0f1 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -40,15 +40,7 @@ LIBRARY_NAME = softokn LIBRARY_VERSION = 3 MAPFILE = $(OBJDIR)/softokn.def -# -# turn this on to get key4 generation and use. -# -# key4.db is properly indexed so we don't have to do db traversals to find keys. -# turning on key4.db will automatically upgrade to key4 on startup if we open -# the directory R/W and key4.db doesn't exist. If we open the directory up -# R/O it opens and used the old key3.db without any update at all. -# -#DEFINES += -DNSS_USE_KEY4_DB +DEFINES += -DSHLIB_SUFFIX=\"${DLL_SUFFIX}\" EXPORTS = \ diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h index d7e48004e..c1d9b3128 100644 --- a/security/nss/lib/softoken/pcert.h +++ b/security/nss/lib/softoken/pcert.h @@ -139,6 +139,7 @@ nsslowcert_DestroyDBEntry(certDBEntry *entry); SECStatus nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, + const char *domain, const char *prefix, NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile); void diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c index b392d36a3..bd50e00e1 100644 --- a/security/nss/lib/softoken/pcertdb.c +++ b/security/nss/lib/softoken/pcertdb.c @@ -541,7 +541,7 @@ static SECStatus DecodeDBCertEntry(certDBEntryCert *entry, SECItem *dbentry) { unsigned int nnlen; - int headerlen; + unsigned int headerlen; int lenoff; /* allow updates of old versions of the database */ @@ -2602,6 +2602,7 @@ ReadDBVersionEntry(NSSLOWCERTCertDBHandle *handle) certDBEntryVersion *entry; SECItem dbkey; SECItem dbentry; + SECStatus rv; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) { @@ -2633,7 +2634,10 @@ ReadDBVersionEntry(NSSLOWCERTCertDBHandle *handle) PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], SEC_DB_VERSION_KEY, SEC_DB_VERSION_KEY_LEN); - ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena); + if (rv != SECSuccess) { + goto loser; + } PORT_FreeArena(tmparena, PR_FALSE); return(entry); @@ -2758,11 +2762,11 @@ AddPermSubjectNode(certDBEntrySubject *entry, NSSLOWCERTCertificate *cert, char *nickname) { SECItem *newCertKeys, *newKeyIDs; - int i; + unsigned int i; SECStatus rv; NSSLOWCERTCertificate *cmpcert; unsigned int nnlen; - int ncerts; + unsigned int ncerts; PORT_Assert(entry); @@ -2860,7 +2864,7 @@ nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertCallback cb, void *cbarg) { certDBEntrySubject *entry; - int i; + unsigned int i; NSSLOWCERTCertificate *cert; SECStatus rv = SECSuccess; @@ -3012,6 +3016,8 @@ nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle, if (entry == NULL) goto loser; if ( entry->nickname == NULL ) { + certDBEntryNickname *nicknameEntry = NULL; + /* no nickname for subject */ rv = AddNicknameToSubject(dbhandle, cert, nickname); if ( rv != SECSuccess ) { @@ -3021,6 +3027,15 @@ nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle, if ( rv != SECSuccess ) { goto loser; } + nicknameEntry = NewDBNicknameEntry(nickname, &cert->derSubject, 0); + if ( nicknameEntry == NULL ) { + goto loser; + } + + rv = WriteDBNicknameEntry(dbhandle, nicknameEntry); + if ( rv != SECSuccess ) { + goto loser; + } } else { /* subject already has a nickname */ rv = AddNicknameToPermCert(dbhandle, cert, entry->nickname); @@ -3535,13 +3550,24 @@ nsslowcert_CertNicknameConflict(char *nickname, SECItem *derSubject, return(rv); } +#ifdef DBM_USING_NSPR +#define NO_RDONLY PR_RDONLY +#define NO_RDWR PR_RDWR +#define NO_CREATE (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE) +#else +#define NO_RDONLY O_RDONLY +#define NO_RDWR O_RDWR +#define NO_CREATE (O_RDWR | O_CREAT | O_TRUNC) +#endif + /* * Open the certificate database and index databases. Create them if * they are not there or bad. */ static SECStatus nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, - NSSLOWCERTDBNameFunc namecb, void *cbarg) + const char *appName, const char *prefix, + NSSLOWCERTDBNameFunc namecb, void *cbarg) { SECStatus rv; int openflags; @@ -3556,17 +3582,17 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, if ( certdbname == NULL ) { return(SECFailure); } - - if ( readOnly ) { - openflags = O_RDONLY; - } else { - openflags = O_RDWR; - } - + + openflags = readOnly ? NO_RDONLY : NO_RDWR; + /* * first open the permanent file based database. */ - handle->permCertDB = dbopen( certdbname, openflags, 0600, DB_HASH, 0 ); + if (appName) { + handle->permCertDB = rdbopen( appName, prefix, "cert", openflags); + } else { + handle->permCertDB = dbopen( certdbname, openflags, 0600, DB_HASH, 0 ); + } /* check for correct version number */ if ( handle->permCertDB ) { @@ -3587,7 +3613,6 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, } } - /* if first open fails, try to create a new DB */ if ( handle->permCertDB == NULL ) { @@ -3596,9 +3621,19 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, goto loser; } - handle->permCertDB = dbopen(certdbname, - O_RDWR | O_CREAT | O_TRUNC, - 0600, DB_HASH, 0); + if (appName) { + handle->permCertDB=rdbopen( appName, prefix, "cert", NO_CREATE); + + updatedb = dbopen(certdbname, NO_RDONLY, 0600, DB_HASH, 0); + if (updatedb) { + db_Copy(handle->permCertDB,updatedb); + (*updatedb->close)(updatedb); + PORT_Free(certdbname); + return(SECSuccess); + } + } else { + handle->permCertDB=dbopen(certdbname, NO_CREATE, 0600, DB_HASH, 0); + } /* if create fails then we lose */ if ( handle->permCertDB == 0 ) { @@ -3621,7 +3656,7 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, /* try to upgrade old db here */ tmpname = (* namecb)(cbarg, 6); /* get v6 db name */ if ( tmpname ) { - updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 ); + updatedb = dbopen( tmpname, NO_RDONLY, 0600, DB_HASH, 0 ); PORT_Free(tmpname); if ( updatedb ) { rv = UpdateV6DB(handle, updatedb); @@ -3632,7 +3667,7 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, } else { /* no v6 db, so try v5 db */ tmpname = (* namecb)(cbarg, 5); /* get v5 db name */ if ( tmpname ) { - updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 ); + updatedb = dbopen( tmpname, NO_RDONLY, 0600, DB_HASH, 0 ); PORT_Free(tmpname); if ( updatedb ) { rv = UpdateV5DB(handle, updatedb); @@ -3644,8 +3679,8 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, /* try to upgrade v4 db */ tmpname = (* namecb)(cbarg, 4); /* get v4 db name */ if ( tmpname ) { - updatedb = dbopen( tmpname, O_RDONLY, 0600, - DB_HASH, 0 ); + updatedb = dbopen( tmpname, NO_RDONLY, 0600, + DB_HASH, 0 ); PORT_Free(tmpname); if ( updatedb ) { /* NES has v5 db's with v4 db names! */ @@ -4045,6 +4080,7 @@ done: */ SECStatus nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, + const char *appName, const char *prefix, NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile) { int rv; @@ -4054,7 +4090,8 @@ nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, handle->dbMon = PZ_NewMonitor(nssILockCertDB); PORT_Assert(handle->dbMon != NULL); - rv = nsslowcert_OpenPermCertDB(handle, readOnly, namecb, cbarg); + rv = nsslowcert_OpenPermCertDB(handle, readOnly, appName, prefix, + namecb, cbarg); if ( rv ) { goto loser; } diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c index fcc906d06..69376db1e 100644 --- a/security/nss/lib/softoken/pk11db.c +++ b/security/nss/lib/softoken/pk11db.c @@ -39,6 +39,7 @@ #include "pk11pars.h" #include "pkcs11i.h" #include "mcom_db.h" +#include "cdbhdl.h" #define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; } @@ -247,13 +248,14 @@ secmod_freeParams(pk11_parameters *params) char * -secmod_getSecmodName(char *param, PRBool *rw) +secmod_getSecmodName(char *param, char **appName, char **filename,PRBool *rw) { int next; char *configdir = NULL; char *secmodName = NULL; char *value = NULL; char *save_params = param; + const char *lconfigdir; param = pk11_argStrip(param); @@ -268,13 +270,15 @@ secmod_getSecmodName(char *param, PRBool *rw) pk11_argHasFlag("flags","noModDB",save_params)) *rw = PR_FALSE; if (!secmodName || *secmodName == '\0') secmodName = PORT_Strdup(SECMOD_DB); + *filename = secmodName; - if (configdir) { - value = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,secmodName); + lconfigdir = pk11_EvaluateConfigDir(configdir, appName); + + if (lconfigdir) { + value = PR_smprintf("%s" PATH_SEPARATOR "%s",lconfigdir,secmodName); } else { - value = PORT_Strdup(secmodName); + value = PR_smprintf("%s",secmodName); } - PORT_Free(secmodName); if (configdir) PORT_Free(configdir); return value; } @@ -296,7 +300,9 @@ static SECStatus secmod_MakeKey(DBT *key, char * module) { } /* free out constructed database key */ -static void secmod_FreeKey(DBT *key) { +static void +secmod_FreeKey(DBT *key) +{ if (key->data) { PORT_Free(key->data); } @@ -359,7 +365,9 @@ struct secmodSlotDataStr { /* * build a data base entry from a module */ -static SECStatus secmod_EncodeData(DBT *data, char * module) { +static SECStatus +secmod_EncodeData(DBT *data, char * module) +{ secmodData *encoded = NULL; secmodSlotData *slot; unsigned char *dataPtr; @@ -437,7 +445,7 @@ static SECStatus secmod_EncodeData(DBT *data, char * module) { SECMOD_PUTLONG(encoded->ssl,ssl[0]); SECMOD_PUTLONG(&encoded->ssl[4],ssl[1]); - offset = (unsigned long) &(((secmodData *)0)->names[0]); + offset = (unsigned short) &(((secmodData *)0)->names[0]); SECMOD_PUTSHORT(encoded->nameStart,offset); offset = offset + len + len2 + len3 + 3*sizeof(unsigned short); SECMOD_PUTSHORT(encoded->slotOffset,offset); @@ -611,8 +619,10 @@ secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal) trustOrder = 100; } - slotStrings[i] = pk11_mkSlotString(slotID,defaultFlags, - timeout,slots[i].askpw,hasRootCerts,hasRootTrust); + slotStrings[i] = pk11_mkSlotString(slotID, defaultFlags, timeout, + (unsigned char)slots[i].askpw, + (unsigned char)hasRootCerts, + (unsigned char)hasRootTrust); } nss = pk11_mkNSS(slotStrings, slotCount, internal, isFIPS, isModuleDB, @@ -626,24 +636,61 @@ secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal) -static DB *secmod_OpenDB(char *dbName, PRBool readOnly) { +static DB * +secmod_OpenDB(const char *appName, const char *filename, const char *dbName, + PRBool readOnly, PRBool update) +{ DB *pkcs11db = NULL; - + + + if (appName) { + char *secname = PORT_Strdup(filename); + int len = strlen(secname); + + if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) { + secname[len-3] = 0; + } + pkcs11db=rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_CREATE); + if (update && !pkcs11db) { + DB *updatedb; + + pkcs11db = rdbopen(appName, "", secname, NO_CREATE); + if (!pkcs11db) { + PORT_Free(secname); + return NULL; + } + updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0); + if (updatedb) { + db_Copy(pkcs11db,updatedb); + (*updatedb->close)(updatedb); + } else { + (*pkcs11db->close)(pkcs11db); + PORT_Free(secname); + return NULL; + } + } + PORT_Free(secname); + return pkcs11db; + } + /* I'm sure we should do more checks here sometime... */ - pkcs11db = dbopen(dbName, readOnly ? O_RDONLY : O_RDWR, 0600, DB_HASH, 0); + pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0); /* didn't exist? create it */ if (pkcs11db == NULL) { - if (readOnly) return NULL; + if (readOnly) + return NULL; - pkcs11db = dbopen( dbName, - O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); - if (pkcs11db) (* pkcs11db->sync)(pkcs11db, 0); + pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 ); + if (pkcs11db) + (* pkcs11db->sync)(pkcs11db, 0); } return pkcs11db; } -static void secmod_CloseDB(DB *pkcs11db) { +static void +secmod_CloseDB(DB *pkcs11db) +{ (*pkcs11db->close)(pkcs11db); } @@ -676,12 +723,14 @@ secmod_addEscape(const char *string, char quote) } #define SECMOD_STEP 10 -#define PK11_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=0 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\"" +#define PK11_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\"" /* * Read all the existing modules in */ char ** -secmod_ReadPermDB(char *dbname, char *params, PRBool rw) { +secmod_ReadPermDB(const char *appName, const char *filename, + const char *dbname, char *params, PRBool rw) +{ DBT key,data; int ret; DB *pkcs11db = NULL; @@ -692,7 +741,7 @@ secmod_ReadPermDB(char *dbname, char *params, PRBool rw) { moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **)); if (moduleList == NULL) return NULL; - pkcs11db = secmod_OpenDB(dbname,PR_TRUE); + pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_TRUE,rw); if (pkcs11db == NULL) goto done; /* read and parse the file or data base */ @@ -734,16 +783,30 @@ done: if (pkcs11db) { secmod_CloseDB(pkcs11db); } else { - secmod_AddPermDB(dbname,moduleList[0], rw) ; + secmod_AddPermDB(appName,filename,dbname,moduleList[0], rw) ; } return moduleList; } +SECStatus +secmod_ReleasePermDBData(const char *appName, const char *filename, + const char *dbname, char **moduleSpecList, PRBool rw) +{ + char **index; + for(index = moduleSpecList; *index; index++) { + PR_smprintf_free(*index); + } + PORT_Free(moduleSpecList); + return SECSuccess; +} + /* * Delete a module from the Data Base */ SECStatus -secmod_DeletePermDB(char *dbname, char *args, PRBool rw) { +secmod_DeletePermDB(const char *appName, const char *filename, + const char *dbname, char *args, PRBool rw) +{ DBT key; SECStatus rv = SECFailure; DB *pkcs11db = NULL; @@ -752,7 +815,7 @@ secmod_DeletePermDB(char *dbname, char *args, PRBool rw) { if (!rw) return SECFailure; /* make sure we have a db handle */ - pkcs11db = secmod_OpenDB(dbname,PR_FALSE); + pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE); if (pkcs11db == NULL) { return SECFailure; } @@ -777,7 +840,9 @@ done: * Add a module to the Data base */ SECStatus -secmod_AddPermDB(char *dbname, char *module, PRBool rw) { +secmod_AddPermDB(const char *appName, const char *filename, + const char *dbname, char *module, PRBool rw) +{ DBT key,data; SECStatus rv = SECFailure; DB *pkcs11db = NULL; @@ -787,7 +852,7 @@ secmod_AddPermDB(char *dbname, char *module, PRBool rw) { if (!rw) return SECFailure; /* make sure we have a db handle */ - pkcs11db = secmod_OpenDB(dbname,PR_FALSE); + pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE); if (pkcs11db == NULL) { return SECFailure; } diff --git a/security/nss/lib/softoken/pk11pars.h b/security/nss/lib/softoken/pk11pars.h index 389599a9d..309313f66 100644 --- a/security/nss/lib/softoken/pk11pars.h +++ b/security/nss/lib/softoken/pk11pars.h @@ -692,7 +692,7 @@ pk11_mkSlotFlags(unsigned long defaultFlags) char *string = NULL; for (j=0; j < pk11_argSlotFlagTableSize; j++) { - if (pk11_argSlotFlagTable[j].value == (1<<i)) { + if (pk11_argSlotFlagTable[j].value == (((unsigned long)1)<<i)) { string = pk11_argSlotFlagTable[j].name; break; } diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index e8beefac9..2a6a43a85 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -605,7 +605,8 @@ pk11_handleCertObject(PK11Session *session,PK11Object *object) NSSLOWCERTCertTrust defTrust = { CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN }; - char *label; + char *label = NULL; + char *email = NULL; SECStatus rv; PRBool inDB = PR_TRUE; @@ -646,10 +647,28 @@ pk11_handleCertObject(PK11Session *session,PK11Object *object) if (label) PORT_Free(label); pk11_FreeAttribute(attribute); + if (rv != SECSuccess) { nsslowcert_DestroyCertificate(cert); return CKR_DEVICE_ERROR; } + + /* + * Add a NULL S/MIME profile if necessary. + */ + email = pk11_getString(object,CKA_NETSCAPE_EMAIL); + if (email) { + certDBEntrySMime *entry; + + entry = nsslowcert_ReadDBSMimeEntry(slot->certDB,email); + if (!entry) { + nsslowcert_SaveSMimeProfile(slot->certDB, email, + &cert->derSubject, NULL, NULL); + } else { + nsslowcert_DestroyDBEntry((certDBEntry *)entry); + } + PORT_Free(email); + } object->handle=pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_CERT); nsslowcert_DestroyCertificate(cert); } @@ -1705,7 +1724,7 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) if (arena == NULL) return NULL; privKey = (NSSLOWKEYPrivateKey *) - PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); + PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); if (privKey == NULL) { PORT_FreeArena(arena,PR_FALSE); return NULL; @@ -1893,7 +1912,7 @@ pk11_mkSecretKeyRep(PK11Object *object) if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; } privKey = (NSSLOWKEYPrivateKey *) - PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); + PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; } privKey->arena = arena; @@ -2037,57 +2056,81 @@ pk11_getDefSlotName(CK_SLOT_ID slotID) return buf; } -static CK_ULONG nscSlotCount = 0; -static CK_SLOT_ID_PTR nscSlotList = NULL; -static CK_ULONG nscSlotListSize = 0; -static PLHashTable *nscSlotHashTable = NULL; +static CK_ULONG nscSlotCount[2] = {0 , 0}; +static CK_SLOT_ID_PTR nscSlotList[2] = {NULL, NULL}; +static CK_ULONG nscSlotListSize[2] = {0, 0}; +static PLHashTable *nscSlotHashTable[2] = {NULL, NULL}; + +static int +pk11_GetModuleIndex(CK_SLOT_ID slotID) +{ + if ((slotID == FIPS_SLOT_ID) || (slotID > 100)) { + return NSC_FIPS_MODULE; + } + return NSC_NON_FIPS_MODULE; +} /* look up a slot structure from the ID (used to be a macro when we only * had two slots) */ PK11Slot * pk11_SlotFromID(CK_SLOT_ID slotID) { - return (PK11Slot *)PL_HashTableLookupConst(nscSlotHashTable, (void *)slotID); + int index = pk11_GetModuleIndex(slotID); + return (PK11Slot *)PL_HashTableLookupConst(nscSlotHashTable[index], + (void *)slotID); } PK11Slot * pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle) { - int slotIDIndex = (handle >> 24) & 0xff; + CK_ULONG slotIDIndex = (handle >> 24) & 0x7f; + CK_ULONG moduleIndex = (handle >> 31) & 1; - if (slotIDIndex >= nscSlotCount) { + if (slotIDIndex >= nscSlotCount[moduleIndex]) { return NULL; } - return pk11_SlotFromID(nscSlotList[slotIDIndex]); + return pk11_SlotFromID(nscSlotList[moduleIndex][slotIDIndex]); } -PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID slotID) +PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID slotID, int moduleIndex) { PK11Slot *slot = NULL; PLHashEntry *entry; + int index; - if (nscSlotList == NULL) { - nscSlotListSize = NSC_SLOT_LIST_BLOCK_SIZE; - nscSlotList = (CK_SLOT_ID *) - PORT_ZAlloc(nscSlotListSize*sizeof(CK_SLOT_ID)); - if (nscSlotList == NULL) { + index = pk11_GetModuleIndex(slotID); + + /* make sure the slotID for this module is valid */ + if (moduleIndex != index) { + return NULL; + } + + if (nscSlotList[index] == NULL) { + nscSlotListSize[index] = NSC_SLOT_LIST_BLOCK_SIZE; + nscSlotList[index] = (CK_SLOT_ID *) + PORT_ZAlloc(nscSlotListSize[index]*sizeof(CK_SLOT_ID)); + if (nscSlotList[index] == NULL) { return NULL; } } - if (nscSlotCount >= nscSlotListSize) { - nscSlotListSize += NSC_SLOT_LIST_BLOCK_SIZE; - nscSlotList = (CK_SLOT_ID *) PORT_Realloc(nscSlotList, - nscSlotListSize*sizeof(CK_SLOT_ID)); - if (nscSlotList == NULL) { - return NULL; + if (nscSlotCount[index] >= nscSlotListSize[index]) { + CK_SLOT_ID* oldNscSlotList = nscSlotList[index]; + CK_ULONG oldNscSlotListSize = nscSlotListSize[index]; + nscSlotListSize[index] += NSC_SLOT_LIST_BLOCK_SIZE; + nscSlotList[index] = (CK_SLOT_ID *) PORT_Realloc(oldNscSlotList, + nscSlotListSize[index]*sizeof(CK_SLOT_ID)); + if (nscSlotList[index] == NULL) { + nscSlotList[index] = oldNscSlotList; + nscSlotListSize[index] = oldNscSlotListSize; + return NULL; } } - if (nscSlotHashTable == NULL) { - nscSlotHashTable = PL_NewHashTable(64,pk11_HashNumber,PL_CompareValues, - PL_CompareValues, NULL, 0); - if (nscSlotHashTable == NULL) { + if (nscSlotHashTable[index] == NULL) { + nscSlotHashTable[index] = PL_NewHashTable(64,pk11_HashNumber, + PL_CompareValues, PL_CompareValues, NULL, 0); + if (nscSlotHashTable[index] == NULL) { return NULL; } } @@ -2097,13 +2140,13 @@ PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID slotID) return NULL; } - entry = PL_HashTableAdd(nscSlotHashTable,(void *)slotID,slot); + entry = PL_HashTableAdd(nscSlotHashTable[index],(void *)slotID,slot); if (entry == NULL) { PORT_Free(slot); return NULL; } - slot->index = nscSlotCount; - nscSlotList[nscSlotCount++] = slotID; + slot->index = (nscSlotCount[index] & 0x7f) | ((index << 7) & 0x80); + nscSlotList[index][nscSlotCount[index]++] = slotID; return slot; } @@ -2112,11 +2155,11 @@ PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID slotID) * initialize one of the slot structures. figure out which by the ID */ CK_RV -PK11_SlotInit(char *configdir,pk11_token_parameters *params) +PK11_SlotInit(char *configdir,pk11_token_parameters *params, int moduleIndex) { int i; CK_SLOT_ID slotID = params->slotID; - PK11Slot *slot = pk11_NewSlotFromID(slotID); + PK11Slot *slot = pk11_NewSlotFromID(slotID, moduleIndex); PRBool needLogin = !params->noKeyDB; CK_RV crv; @@ -2257,34 +2300,92 @@ pk11_DestroySlotData(PK11Slot *slot) * handle the SECMOD.db */ char ** -NSC_ModuleDBFunc(unsigned long function,char *parameters, char *args) +NSC_ModuleDBFunc(unsigned long function,char *parameters, void *args) { - char *secmod; + char *secmod = NULL; + char *appName = NULL; + char *filename = NULL; PRBool rw; static char *success="Success"; char **rvstr = NULL; - secmod = secmod_getSecmodName(parameters,&rw); + secmod = secmod_getSecmodName(parameters,&appName,&filename, &rw); switch (function) { case SECMOD_MODULE_DB_FUNCTION_FIND: - rvstr = secmod_ReadPermDB(secmod,parameters,rw); + rvstr = secmod_ReadPermDB(appName,filename,secmod,(char *)parameters,rw); break; case SECMOD_MODULE_DB_FUNCTION_ADD: - rvstr = (secmod_AddPermDB(secmod,args,rw) == SECSuccess) - ? &success: NULL; + rvstr = (secmod_AddPermDB(appName,filename,secmod,(char *)args,rw) + == SECSuccess) ? &success: NULL; break; case SECMOD_MODULE_DB_FUNCTION_DEL: - rvstr = (secmod_DeletePermDB(secmod,args,rw) == SECSuccess) - ? &success: NULL; + rvstr = (secmod_DeletePermDB(appName,filename,secmod,(char *)args,rw) + == SECSuccess) ? &success: NULL; + break; + case SECMOD_MODULE_DB_FUNCTION_RELEASE: + rvstr = (secmod_ReleasePermDBData(appName,filename,secmod, + (char **)args,rw) == SECSuccess) ? &success: NULL; break; } if (secmod) PR_smprintf_free(secmod); + if (appName) PORT_Free(appName); + if (filename) PORT_Free(filename); return rvstr; } +static void nscFreeAllSlots(int moduleIndex) +{ + /* free all the slots */ + PK11Slot *slot = NULL; + CK_SLOT_ID slotID; + int i; + + if (nscSlotList[moduleIndex]) { + CK_ULONG tmpSlotCount = nscSlotCount[moduleIndex]; + CK_SLOT_ID_PTR tmpSlotList = nscSlotList[moduleIndex]; + PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; + + /* now clear out the statics */ + nscSlotList[moduleIndex] = NULL; + nscSlotCount[moduleIndex] = 0; + nscSlotHashTable[moduleIndex] = NULL; + nscSlotListSize[moduleIndex] = 0; + + for (i=0; i < (int) tmpSlotCount; i++) { + slotID = tmpSlotList[i]; + slot = (PK11Slot *) + PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); + PORT_Assert(slot); + if (!slot) continue; + pk11_DestroySlotData(slot); + PL_HashTableRemove(tmpSlotHashTable, (void *)slotID); + } + PORT_Free(tmpSlotList); + PL_HashTableDestroy(tmpSlotHashTable); + } +} + +static void +pk11_closePeer(PRBool isFIPS) +{ + CK_SLOT_ID slotID = isFIPS ? PRIVATE_KEY_SLOT_ID: FIPS_SLOT_ID; + PK11Slot *slot; + int moduleIndex = isFIPS? NSC_NON_FIPS_MODULE : NSC_FIPS_MODULE; + PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; + + slot = (PK11Slot *) PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); + if (slot == NULL) { + return; + } + pk11_DBShutdown(slot->certDB,slot->keyDB); + slot->certDB = NULL; + slot->keyDB = NULL; + return; +} static PRBool nsc_init = PR_FALSE; + /* NSC_Initialize initializes the Cryptoki library. */ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) { @@ -2292,10 +2393,7 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) SECStatus rv; CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved; int i; - - if (nsc_init) { - return crv; - } + int moduleIndex = isFIPS? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE; rv = RNG_RNGInit(); /* initialize random number generator */ if (rv != SECSuccess) { @@ -2328,59 +2426,53 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) goto loser; } + /* if we have a peer already open, have him close his DB's so we + * don't clobber each other. */ + if ((isFIPS && nsc_init) || (!isFIPS && nsf_init)) { + pk11_closePeer(isFIPS); + } + for (i=0; i < paramStrings.token_count; i++) { crv = - PK11_SlotInit(paramStrings.configdir, ¶mStrings.tokens[i]); - if (crv != CKR_OK) break; + PK11_SlotInit(paramStrings.configdir, ¶mStrings.tokens[i], + moduleIndex); + if (crv != CKR_OK) { + nscFreeAllSlots(moduleIndex); + break; + } } loser: secmod_freeParams(¶mStrings); } - nsc_init = (PRBool) (crv == CKR_OK); return crv; } CK_RV NSC_Initialize(CK_VOID_PTR pReserved) { - return nsc_CommonInitialize(pReserved,PR_FALSE); + CK_RV crv; + if (nsc_init) { + return CKR_CRYPTOKI_ALREADY_INITIALIZED; + } + crv = nsc_CommonInitialize(pReserved,PR_FALSE); + nsc_init = (PRBool) (crv == CKR_OK); + return crv; } /* NSC_Finalize indicates that an application is done with the * Cryptoki library.*/ -CK_RV NSC_Finalize (CK_VOID_PTR pReserved) +CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS) { - PK11Slot *slot = NULL; - CK_SLOT_ID slotID; - int i; + - if (!nsc_init) { + nscFreeAllSlots(isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE); + + /* don't muck with the globals is our peer is still initialized */ + if (isFIPS && nsc_init) { return CKR_OK; } - - /* free all the slots */ - if (nscSlotList) { - CK_ULONG tmpSlotCount = nscSlotCount; - CK_SLOT_ID_PTR tmpSlotList = nscSlotList; - PLHashTable *tmpSlotHashTable = nscSlotHashTable; - - /* now clear out the statics */ - nscSlotList = NULL; - nscSlotCount = 0; - nscSlotHashTable = NULL; - nscSlotListSize = 0; - - for (i=0; i < tmpSlotCount; i++) { - slotID = tmpSlotList[i]; - slot = (PK11Slot *) - PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); - PORT_Assert(slot); - if (!slot) continue; - pk11_DestroySlotData(slot); - PL_HashTableRemove(tmpSlotHashTable, (void *)slotID); - } - PORT_Free(tmpSlotList); - PL_HashTableDestroy(tmpSlotHashTable); + if (!isFIPS && nsf_init) { + return CKR_OK; } nsslowcert_DestroyGlobalLocks(); @@ -2406,6 +2498,23 @@ CK_RV NSC_Finalize (CK_VOID_PTR pReserved) return CKR_OK; } +/* NSC_Finalize indicates that an application is done with the + * Cryptoki library.*/ +CK_RV NSC_Finalize (CK_VOID_PTR pReserved) +{ + CK_RV crv; + + if (!nsc_init) { + return CKR_OK; + } + + crv = nsc_CommonFinalize (pReserved, PR_FALSE); + + nsc_init = (PRBool) !(crv == CKR_OK); + + return crv; +} + extern const char __nss_softokn_rcsid[]; extern const char __nss_softokn_sccsid[]; @@ -2425,16 +2534,26 @@ CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) return CKR_OK; } + /* NSC_GetSlotList obtains a list of slots in the system. */ -CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, - CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) +CK_RV nsc_CommonGetSlotList(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex) { - *pulCount = nscSlotCount; + *pulCount = nscSlotCount[moduleIndex]; if (pSlotList != NULL) { - PORT_Memcpy(pSlotList,nscSlotList,nscSlotCount*sizeof(CK_SLOT_ID)); + PORT_Memcpy(pSlotList,nscSlotList[moduleIndex], + nscSlotCount[moduleIndex]*sizeof(CK_SLOT_ID)); } return CKR_OK; } + +/* NSC_GetSlotList obtains a list of slots in the system. */ +CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) +{ + return nsc_CommonGetSlotList(tokenPresent, pSlotList, pulCount, + NSC_NON_FIPS_MODULE); +} /* NSC_GetSlotInfo obtains information about a particular slot in the system. */ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) @@ -2701,7 +2820,7 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, if (ulPinLen > PK11_MAX_PIN) { return CKR_PIN_LEN_RANGE; } - if (ulPinLen < slot->minimumPinLen) { + if (ulPinLen < (CK_ULONG)slot->minimumPinLen) { return CKR_PIN_LEN_RANGE; } @@ -2776,7 +2895,7 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, if ((ulNewLen > PK11_MAX_PIN) || (ulOldLen > PK11_MAX_PIN)) { return CKR_PIN_LEN_RANGE; } - if (ulNewLen < slot->minimumPinLen) { + if (ulNewLen < (CK_ULONG)slot->minimumPinLen) { return CKR_PIN_LEN_RANGE; } @@ -3213,7 +3332,6 @@ CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession, if (crv != CKR_OK) { pk11_FreeObject(destObject); pk11_FreeSession(session); - return crv; } crv = pk11_handleObject(destObject,session); @@ -3488,6 +3606,16 @@ pk11_key_collect(DBT *key, DBT *data, void *arg) if (keyData->id->len == 0) { haveMatch = PR_TRUE; /* taking any key */ + /* Make sure this isn't a NSC_KEY */ + privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB, + &tmpDBKey, keyData->slot->password); + if (privKey) { + haveMatch = isSecretKey(privKey) ? + (PRBool)(keyData->classFlags & NSC_KEY) != 0: + (PRBool)(keyData->classFlags & + (NSC_PRIVATE|NSC_PUBLIC)) != 0; + nsslowkey_DestroyPrivateKey(privKey); + } } else { SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */ haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result); @@ -3571,15 +3699,15 @@ pk11_searchKeys(PK11Slot *slot, SECItem *key_id, PRBool isLoggedIn, if (key_id->data) { privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, slot->password); if (privKey) { - if (classFlags & NSC_KEY) { + if ((classFlags & NSC_KEY) && isSecretKey(privKey)) { pk11_addHandle(search, pk11_mkHandle(slot,key_id,PK11_TOKEN_TYPE_KEY)); } - if (classFlags & NSC_PRIVATE) { + if ((classFlags & NSC_PRIVATE) && !isSecretKey(privKey)) { pk11_addHandle(search, pk11_mkHandle(slot,key_id,PK11_TOKEN_TYPE_PRIV)); } - if (classFlags & NSC_PUBLIC) { + if ((classFlags & NSC_PUBLIC) && !isSecretKey(privKey)) { pk11_addHandle(search, pk11_mkHandle(slot,key_id,PK11_TOKEN_TYPE_PUB)); } diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index 391f2f152..af3350cd0 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -90,6 +90,9 @@ #define NSC_SEARCH_BLOCK_SIZE 5 #define NSC_SLOT_LIST_BLOCK_SIZE 10 +#define NSC_FIPS_MODULE 1 +#define NSC_NON_FIPS_MODULE 0 + /* these are data base storage hashes, not cryptographic hashes.. The define * the effective size of the various object hash tables */ #ifdef MOZ_CLIENT @@ -113,6 +116,8 @@ #endif #define MAX_KEY_LEN 256 +#define MULTIACCESS "multiaccess:" + /* * LOG2_BUCKETS_PER_SESSION_LOCK must be a prime number. * With SESSION_HASH_SIZE=1024, LOG2 can be 9, 5, 1, or 0. @@ -519,9 +524,14 @@ typedef struct pk11_parametersStr { SEC_BEGIN_PROTOS +extern int nsf_init; extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS); +extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS); +extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent, + CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex); /* shared functions between PKCS11.c and PK11FIPS.c */ -extern CK_RV PK11_SlotInit(char *configdir,pk11_token_parameters *params); +extern CK_RV PK11_SlotInit(char *configdir,pk11_token_parameters *params, + int moduleIndex); /* internal utility functions used by pkcs11.c */ extern PK11Attribute *pk11_FindAttribute(PK11Object *object, @@ -594,10 +604,16 @@ extern PRBool pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type); extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed, PRBool isFIPS); extern void secmod_freeParams(pk11_parameters *params); -extern char *secmod_getSecmodName(char *params, PRBool *rw); -extern char ** secmod_ReadPermDB(char *dbname, char *params, PRBool rw); -extern SECStatus secmod_DeletePermDB(char *dbname,char *args, PRBool rw); -extern SECStatus secmod_AddPermDB(char *dbname, char *module, PRBool rw); +extern char *secmod_getSecmodName(char *params, char **domain, + char **filename, PRBool *rw); +extern char ** secmod_ReadPermDB(const char *domain, const char *filename, + const char *dbname, char *params, PRBool rw); +extern SECStatus secmod_DeletePermDB(const char *domain, const char *filename, + const char *dbname, char *args, PRBool rw); +extern SECStatus secmod_AddPermDB(const char *domain, const char *filename, + const char *dbname, char *module, PRBool rw); +extern SECStatus secmod_ReleasePermDBData(const char *domain, + const char *filename, const char *dbname, char **specList, PRBool rw); /* * OK there are now lots of options here, lets go through them all: * @@ -623,6 +639,8 @@ CK_RV pk11_DBInit(const char *configdir, const char *certPrefix, void pk11_DBShutdown(NSSLOWCERTCertDBHandle *certHandle, NSSLOWKEYDBHandle *keyHandle); +const char *pk11_EvaluateConfigDir(const char *configdir, char **domain); + /* * narrow objects */ diff --git a/security/nss/lib/softoken/pkcs11n.h b/security/nss/lib/softoken/pkcs11n.h index 7ee4c6c34..c2b57acab 100644 --- a/security/nss/lib/softoken/pkcs11n.h +++ b/security/nss/lib/softoken/pkcs11n.h @@ -213,11 +213,13 @@ typedef CK_ULONG CK_TRUST; * The function 'ADD' takes a PKCS #11 initialization string and stores it. * The function 'DEL' takes a 'name= library=' value and deletes the associated * string. + * The function 'RELEASE' frees the array returned by 'FIND' */ #define SECMOD_MODULE_DB_FUNCTION_FIND 0 #define SECMOD_MODULE_DB_FUNCTION_ADD 1 #define SECMOD_MODULE_DB_FUNCTION_DEL 2 +#define SECMOD_MODULE_DB_FUNCTION_RELEASE 3 typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function, - char *parameters, char *moduleSpec); + char *parameters, void *moduleSpec); #endif /* _PKCS11N_H_ */ diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 2dd69ed39..5e42975e0 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -1261,6 +1261,50 @@ pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) } pk11_FreeAttribute(attribute); } + +static CK_RV +pk11_SetCertAttribute(PK11TokenObject *to, CK_ATTRIBUTE_TYPE type, + void *value, unsigned int len) +{ + NSSLOWCERTCertificate *cert; + char *nickname = NULL; + SECStatus rv; + + /* we can't change the ID or the EMAIL values, but let the + * upper layers feel better about the fact we tried to set these */ + if ((type == CKA_ID) || (type == CKA_NETSCAPE_EMAIL)) { + return CKR_OK; + } + + if (to->obj.slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + + if (type != CKA_LABEL) { + return CKR_ATTRIBUTE_READ_ONLY; + } + + cert = pk11_getCert(to); + if (cert == NULL) { + return CKR_OBJECT_HANDLE_INVALID; + } + + if (value != NULL) { + nickname = PORT_ZAlloc(len+1); + if (nickname == NULL) { + return CKR_HOST_MEMORY; + } + PORT_Memcpy(nickname,value,len); + nickname[len] = 0; + } + rv = nsslowcert_AddPermNickname(to->obj.slot->certDB, cert, nickname); + if (nickname) PORT_Free(nickname); + if (rv != SECSuccess) { + return CKR_DEVICE_ERROR; + } + return CKR_OK; +} + static CK_RV pk11_SetPrivateKeyAttribute(PK11TokenObject *to, CK_ATTRIBUTE_TYPE type, void *value, unsigned int len) @@ -1381,6 +1425,7 @@ pk11_forceTokenAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, switch (object->objclass) { case CKO_CERTIFICATE: /* change NICKNAME, EMAIL, */ + crv = pk11_SetCertAttribute(to,type,value,len); break; case CKO_NETSCAPE_CRL: /* change URL */ diff --git a/security/nss/lib/softoken/softokn.rc b/security/nss/lib/softoken/softokn.rc index 8c4c6f7c6..a6477ed12 100644 --- a/security/nss/lib/softoken/softokn.rc +++ b/security/nss/lib/softoken/softokn.rc @@ -34,13 +34,21 @@ #include "nss.h" #include <winver.h> -#define MY_LIBNAME "softokn" +#define MY_LIBNAME "softoken" #ifdef MOZ_CLIENT -#define MY_FILEDESCRIPTION "NSS Builtin Crypto PKCS #11 Library for Clients" +#define CLIENTS " for Clients" #else -#define MY_FILEDESCRIPTION "NSS Builtin Crypto PKCS #11 Library" +#define CLIENTS "" #endif +#ifdef REMOTE_DBM +#define DBM " with Shared Database" +#else +#define DBM "" +#endif + +#define MY_FILEDESCRIPTION "NSS PKCS #11 Library" CLIENTS DBM + #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) #define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR) diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index a1d09e814..e9dfe6f31 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -1289,12 +1289,12 @@ SEC_END_PROTOS #endif #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) -#define SSL_GETPID() getpid() +#define SSL_GETPID getpid +#elif defined(_WIN32_WCE) +#define SSL_GETPID GetCurrentProcessId #elif defined(WIN32) - extern int __cdecl _getpid(void); -/* #define SSL_GETPID() GetCurrentProcessId() */ -#define SSL_GETPID() _getpid() +#define SSL_GETPID _getpid #else #define SSL_GETPID() 0 #endif diff --git a/security/nss/lib/ssl/sslmutex.c b/security/nss/lib/ssl/sslmutex.c index 6f88c27d8..85d6e88c2 100644 --- a/security/nss/lib/ssl/sslmutex.c +++ b/security/nss/lib/ssl/sslmutex.c @@ -33,6 +33,10 @@ * $Id$ */ +#include "seccomon.h" +/* This ifdef should match the one in sslsnce.c */ +#if (defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)) && !defined(_WIN32_WCE) + #include "sslmutex.h" #include "prerr.h" @@ -83,7 +87,7 @@ static SECStatus single_process_sslMutex_Lock(sslMutex* pMutex) return SECSuccess; } -#if defined(LINUX) || defined(AIX) || defined(VMS) || defined(BEOS) || defined(BSDI) +#if defined(LINUX) || defined(AIX) || defined(VMS) || defined(BEOS) || defined(BSDI) || defined(NETBSD) || defined(OPENBSD) #include <unistd.h> #include <fcntl.h> @@ -504,7 +508,9 @@ sslMutex_Lock(sslMutex *pMutex) break; case WAIT_TIMEOUT: +#if defined(WAIT_IO_COMPLETION) case WAIT_IO_COMPLETION: +#endif default: /* should never happen. nothing we can do. */ PR_ASSERT(!("WaitForSingleObject returned invalid value.")); PORT_SetError(PR_UNKNOWN_ERROR); @@ -652,3 +658,5 @@ sslMutex_Lock(sslMutex *pMutex) } #endif + +#endif diff --git a/security/nss/lib/ssl/sslmutex.h b/security/nss/lib/ssl/sslmutex.h index 4ede0eba3..97115782f 100644 --- a/security/nss/lib/ssl/sslmutex.h +++ b/security/nss/lib/ssl/sslmutex.h @@ -77,7 +77,7 @@ typedef struct typedef int sslPID; -#elif defined(LINUX) || defined(AIX) || defined(VMS) || defined(BEOS) || defined(BSDI) +#elif defined(LINUX) || defined(AIX) || defined(VMS) || defined(BEOS) || defined(BSDI) || defined(NETBSD) || defined(OPENBSD) #include <sys/types.h> #include "prtypes.h" diff --git a/security/nss/lib/ssl/sslnonce.c b/security/nss/lib/ssl/sslnonce.c index 36dd7f073..ac79c6d66 100644 --- a/security/nss/lib/ssl/sslnonce.c +++ b/security/nss/lib/ssl/sslnonce.c @@ -44,7 +44,7 @@ #include "sslproto.h" #include "nssilock.h" #include "nsslocks.h" -#if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) +#if (defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS)) && !defined(_WIN32_WCE) #include <time.h> #endif @@ -348,7 +348,7 @@ PRUint32 ssl_Time(void) { PRUint32 myTime; -#if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) +#if (defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS)) && !defined(_WIN32_WCE) myTime = time(NULL); /* accurate until the year 2038. */ #else /* portable, but possibly slower */ diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index 85bb024c8..e5c2bc136 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -43,16 +43,6 @@ #include "secoid.h" /* for SECOID_GetALgorithmTag */ #include "pk11func.h" /* for PK11_GenerateRandom */ -#if defined(_WINDOWS) -#include "winsock.h" /* for MSG_PEEK */ -#elif defined(XP_MAC) -#include "macsocket.h" -#elif defined(BEOS) -#define MSG_PEEK 0x2 -#else -#include <sys/socket.h> /* for MSG_PEEK */ -#endif - #define MAX_BLOCK_CYPHER_SIZE 32 #define TEST_FOR_FAILURE /* reminder */ @@ -549,7 +539,7 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags) /* Dole out clear data to reader */ amount = PR_MIN(len, available); PORT_Memcpy(out, ss->gs.buf.buf + ss->gs.readOffset, amount); - if (!(flags & MSG_PEEK)) { + if (!(flags & PR_MSG_PEEK)) { ss->gs.readOffset += amount; } rv = amount; @@ -952,7 +942,7 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR); return PR_FAILURE; } - if (flags & ~MSG_PEEK) { + if (flags & ~PR_MSG_PEEK) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); return PR_FAILURE; } diff --git a/security/nss/lib/ssl/sslsnce.c b/security/nss/lib/ssl/sslsnce.c index f69f3fd42..f4d4d08d3 100644 --- a/security/nss/lib/ssl/sslsnce.c +++ b/security/nss/lib/ssl/sslsnce.c @@ -69,7 +69,7 @@ #include "nssrenam.h" #include "seccomon.h" -#if defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS) +#if (defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)) && !defined(_WIN32_WCE) #include "cert.h" #include "ssl.h" diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 0042924b8..1025cc609 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -1801,7 +1801,7 @@ ssl_NewSocket(void) { sslSocket *ss; #ifdef DEBUG -#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS) +#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)) && !defined(_WIN32_WCE) static int firsttime = 1; if (firsttime) { diff --git a/security/nss/lib/ssl/win32err.c b/security/nss/lib/ssl/win32err.c index acfce2c9d..4f55f280c 100644 --- a/security/nss/lib/ssl/win32err.c +++ b/security/nss/lib/ssl/win32err.c @@ -41,6 +41,8 @@ * $Id$ */ +#if !defined(_WIN32_WCE) + #include "prerror.h" #include "prlog.h" #include <errno.h> @@ -371,3 +373,4 @@ void nss_MD_win32_map_default_error(PRInt32 err) PR_SetError(prError, err); } +#endif diff --git a/security/nss/lib/util/Makefile b/security/nss/lib/util/Makefile index 26b783874..0236afefa 100644 --- a/security/nss/lib/util/Makefile +++ b/security/nss/lib/util/Makefile @@ -47,8 +47,10 @@ include manifest.mn include $(CORE_DEPTH)/coreconf/config.mk ifeq ($(OS_TARGET),HP-UX) +ifneq ($(OS_TEST),ia64) ASFILES += ret_cr16.s endif +endif ####################################################################### # (3) Include "component" configuration information. (OPTIONAL) # diff --git a/security/nss/lib/util/dersubr.c b/security/nss/lib/util/dersubr.c index dc91ffe6f..a61eee760 100644 --- a/security/nss/lib/util/dersubr.c +++ b/security/nss/lib/util/dersubr.c @@ -62,10 +62,10 @@ DER_StoreHeader(unsigned char *buf, unsigned int code, uint32 len) { unsigned char b[4]; - b[0] = (len >> 24) & 0xff; - b[1] = (len >> 16) & 0xff; - b[2] = (len >> 8) & 0xff; - b[3] = len & 0xff; + b[0] = (unsigned char)(len >> 24); + b[1] = (unsigned char)(len >> 16); + b[2] = (unsigned char)(len >> 8); + b[3] = (unsigned char)len; if ((code & DER_TAGNUM_MASK) == DER_SET || (code & DER_TAGNUM_MASK) == DER_SEQUENCE) code |= DER_CONSTRUCTED; diff --git a/security/nss/lib/util/manifest.mn b/security/nss/lib/util/manifest.mn index 60ebb1fae..fc9a38094 100644 --- a/security/nss/lib/util/manifest.mn +++ b/security/nss/lib/util/manifest.mn @@ -59,8 +59,6 @@ EXPORTS = \ watcomfx.h \ $(NULL) -MODULE = security - CSRCS = \ secdig.c \ derdec.c \ @@ -86,6 +84,9 @@ CSRCS = \ utf8.c \ $(NULL) -REQUIRES = security dbm +MODULE = security + +# don't duplicate module name in REQUIRES +REQUIRES = dbm LIBRARY_NAME = secutil diff --git a/security/nss/lib/util/secder.h b/security/nss/lib/util/secder.h index 3f957ab9c..fdd43b1de 100644 --- a/security/nss/lib/util/secder.h +++ b/security/nss/lib/util/secder.h @@ -41,7 +41,11 @@ * $Id$ */ +#if defined(_WIN32_WCE) +#else #include <time.h> +#endif + #include "plarena.h" #include "prlong.h" diff --git a/security/nss/lib/util/secerr.h b/security/nss/lib/util/secerr.h index ff9c784ee..0742d7386 100644 --- a/security/nss/lib/util/secerr.h +++ b/security/nss/lib/util/secerr.h @@ -179,7 +179,8 @@ SEC_ERROR_OCSP_FUTURE_RESPONSE = (SEC_ERROR_BASE + 131), SEC_ERROR_OCSP_OLD_RESPONSE = (SEC_ERROR_BASE + 132), /* smime stuff */ SEC_ERROR_DIGEST_NOT_FOUND = (SEC_ERROR_BASE + 133), -SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE = (SEC_ERROR_BASE + 134) +SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE = (SEC_ERROR_BASE + 134), +SEC_ERROR_MODULE_STUCK = (SEC_ERROR_BASE + 135) } SECErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/security/nss/lib/util/secoid.c b/security/nss/lib/util/secoid.c index d7a74ae7a..1ad0aa197 100644 --- a/security/nss/lib/util/secoid.c +++ b/security/nss/lib/util/secoid.c @@ -61,7 +61,7 @@ #define NETSCAPE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42 #define NETSCAPE_CERT_EXT NETSCAPE_OID, 0x01 #define NETSCAPE_DATA_TYPE NETSCAPE_OID, 0x02 -/* netscape directory oid - owned by Tim Howes(howes@netscape.com) */ +/* netscape directory oid - owned by Mark Smith (mcs@netscape.com) */ #define NETSCAPE_DIRECTORY NETSCAPE_OID, 0x03 #define NETSCAPE_POLICY NETSCAPE_OID, 0x04 #define NETSCAPE_CERT_SERVER NETSCAPE_OID, 0x05 @@ -264,6 +264,9 @@ CONST_OID nsExtCertRenewalTime[] = { NETSCAPE_CERT_EXT, 0x0f }; CONST_OID nsExtAIACertRenewal[] = { NETSCAPE_CERT_EXT_AIA, 0x01 }; CONST_OID nsExtCertScopeOfUse[] = { NETSCAPE_CERT_EXT, 0x11 }; +/* Reserved Netscape (2 16 840 1 113730 1 18) = { NETSCAPE_CERT_EXT, 0x12 }; */ + +/* Netscape policy values */ CONST_OID nsKeyUsageGovtApproved[] = { NETSCAPE_POLICY, 0x01 }; /* Netscape other name types */ diff --git a/security/nss/lib/util/secport.c b/security/nss/lib/util/secport.c index bfde55a81..276cf6208 100644 --- a/security/nss/lib/util/secport.c +++ b/security/nss/lib/util/secport.c @@ -159,6 +159,19 @@ PORT_ZFree(void *ptr, size_t len) } } +char * +PORT_Strdup(const char *str) +{ + size_t len = PORT_Strlen(str)+1; + char *newstr; + + newstr = (char *)PORT_Alloc(len); + if (newstr) { + PORT_Memcpy(newstr, str, len); + } + return newstr; +} + void PORT_SetError(int value) { @@ -258,6 +271,12 @@ PORT_FreeArena(PLArenaPool *arena, PRBool zero) PZ_Lock(lock); } if (!pvd) { + /* Each of NSPR's DLLs has a function libVersionPoint(). + ** We could do a lot of extra work to be sure we're calling the + ** one in the DLL that holds PR_FreeArenaPool, but instead we + ** rely on the fact that ALL NSPR DLLs in the same directory + ** must be from the same release, and we call which ever one we get. + */ /* no need for thread protection here */ pvd = libVersionPoint(); if ((pvd->vMajor > 4) || @@ -440,7 +459,7 @@ PORT_ArenaUnmark(PLArenaPool *arena, void *mark) } char * -PORT_ArenaStrdup(PLArenaPool *arena, char *str) { +PORT_ArenaStrdup(PLArenaPool *arena, const char *str) { int len = PORT_Strlen(str)+1; char *newstr; @@ -529,7 +548,7 @@ PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf, int NSS_PutEnv(const char * envVarName, const char * envValue) { -#if defined(XP_MAC) +#if defined(XP_MAC) || defined(_WIN32_WCE) return SECFailure; #else SECStatus result = SECSuccess; diff --git a/security/nss/lib/util/secport.h b/security/nss/lib/util/secport.h index c89c7dcd5..b154c0915 100644 --- a/security/nss/lib/util/secport.h +++ b/security/nss/lib/util/secport.h @@ -85,7 +85,10 @@ #include "watcomfx.h" #endif -#ifdef XP_MAC +#if defined(_WIN32_WCE) +#include <windef.h> +#include <types.h> +#elif defined( XP_MAC ) #include <types.h> #include <time.h> /* for time_t below */ #else @@ -100,7 +103,11 @@ #include <ctype.h> #include <string.h> +#if defined(_WIN32_WCE) +#include <stdlib.h> /* WinCE puts some stddef symbols here. */ +#else #include <stddef.h> +#endif #include <stdlib.h> #include "prtypes.h" #include "prlog.h" /* for PR_ASSERT */ @@ -137,7 +144,7 @@ extern void *PORT_ArenaGrow(PLArenaPool *arena, void *ptr, extern void *PORT_ArenaMark(PLArenaPool *arena); extern void PORT_ArenaRelease(PLArenaPool *arena, void *mark); extern void PORT_ArenaUnmark(PLArenaPool *arena, void *mark); -extern char *PORT_ArenaStrdup(PLArenaPool *arena, char *str); +extern char *PORT_ArenaStrdup(PLArenaPool *arena, const char *str); #ifdef __cplusplus } @@ -203,10 +210,10 @@ extern char *PORT_ArenaStrdup(PLArenaPool *arena, char *str); #define PORT_Strcasecmp PL_strcasecmp #define PORT_Strcat strcat #define PORT_Strchr strchr -#define PORT_Strrchr PL_strrchr +#define PORT_Strrchr strrchr #define PORT_Strcmp strcmp #define PORT_Strcpy strcpy -#define PORT_Strdup PL_strdup +extern char *PORT_Strdup(const char *s); #define PORT_Strlen(s) strlen(s) #define PORT_Strncasecmp PL_strncasecmp #define PORT_Strncat strncat diff --git a/security/nss/macbuild/NSS.xml b/security/nss/macbuild/NSS.xml index ef06cc17c..a9aefb197 100644 --- a/security/nss/macbuild/NSS.xml +++ b/security/nss/macbuild/NSS.xml @@ -1137,13 +1137,6 @@ </FILE> <FILE> <PATHTYPE>Name</PATHTYPE> - <PATH>devobject.c</PATH> - <PATHFORMAT>MacOS</PATHFORMAT> - <FILEKIND>Text</FILEKIND> - <FILEFLAGS></FILEFLAGS> - </FILE> - <FILE> - <PATHTYPE>Name</PATHTYPE> <PATH>devslot.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> <FILEKIND>Text</FILEKIND> @@ -1200,6 +1193,13 @@ </FILE> <FILE> <PATHTYPE>Name</PATHTYPE> + <PATH>pkibase.c</PATH> + <PATHFORMAT>MacOS</PATHFORMAT> + <FILEKIND>Text</FILEKIND> + <FILEFLAGS></FILEFLAGS> + </FILE> + <FILE> + <PATHTYPE>Name</PATHTYPE> <PATH>pkistore.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> <FILEKIND>Text</FILEKIND> @@ -1626,11 +1626,6 @@ </FILEREF> <FILEREF> <PATHTYPE>Name</PATHTYPE> - <PATH>devobject.c</PATH> - <PATHFORMAT>MacOS</PATHFORMAT> - </FILEREF> - <FILEREF> - <PATHTYPE>Name</PATHTYPE> <PATH>devslot.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> </FILEREF> @@ -1671,6 +1666,11 @@ </FILEREF> <FILEREF> <PATHTYPE>Name</PATHTYPE> + <PATH>pkibase.c</PATH> + <PATHFORMAT>MacOS</PATHFORMAT> + </FILEREF> + <FILEREF> + <PATHTYPE>Name</PATHTYPE> <PATH>pkistore.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> </FILEREF> @@ -3155,13 +3155,6 @@ </FILE> <FILE> <PATHTYPE>Name</PATHTYPE> - <PATH>devobject.c</PATH> - <PATHFORMAT>MacOS</PATHFORMAT> - <FILEKIND>Text</FILEKIND> - <FILEFLAGS></FILEFLAGS> - </FILE> - <FILE> - <PATHTYPE>Name</PATHTYPE> <PATH>devslot.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> <FILEKIND>Text</FILEKIND> @@ -3218,6 +3211,13 @@ </FILE> <FILE> <PATHTYPE>Name</PATHTYPE> + <PATH>pkibase.c</PATH> + <PATHFORMAT>MacOS</PATHFORMAT> + <FILEKIND>Text</FILEKIND> + <FILEFLAGS></FILEFLAGS> + </FILE> + <FILE> + <PATHTYPE>Name</PATHTYPE> <PATH>pkistore.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> <FILEKIND>Text</FILEKIND> @@ -3634,11 +3634,6 @@ </FILEREF> <FILEREF> <PATHTYPE>Name</PATHTYPE> - <PATH>devobject.c</PATH> - <PATHFORMAT>MacOS</PATHFORMAT> - </FILEREF> - <FILEREF> - <PATHTYPE>Name</PATHTYPE> <PATH>devslot.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> </FILEREF> @@ -3679,6 +3674,11 @@ </FILEREF> <FILEREF> <PATHTYPE>Name</PATHTYPE> + <PATH>pkibase.c</PATH> + <PATHFORMAT>MacOS</PATHFORMAT> + </FILEREF> + <FILEREF> + <PATHTYPE>Name</PATHTYPE> <PATH>pkistore.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> </FILEREF> @@ -4219,12 +4219,6 @@ <FILEREF> <TARGETNAME>NSS3Debug.shlb</TARGETNAME> <PATHTYPE>Name</PATHTYPE> - <PATH>devobject.c</PATH> - <PATHFORMAT>MacOS</PATHFORMAT> - </FILEREF> - <FILEREF> - <TARGETNAME>NSS3Debug.shlb</TARGETNAME> - <PATHTYPE>Name</PATHTYPE> <PATH>devslot.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> </FILEREF> @@ -4375,6 +4369,12 @@ <FILEREF> <TARGETNAME>NSS3Debug.shlb</TARGETNAME> <PATHTYPE>Name</PATHTYPE> + <PATH>pkibase.c</PATH> + <PATHFORMAT>MacOS</PATHFORMAT> + </FILEREF> + <FILEREF> + <TARGETNAME>NSS3Debug.shlb</TARGETNAME> + <PATHTYPE>Name</PATHTYPE> <PATH>pkistore.c</PATH> <PATHFORMAT>MacOS</PATHFORMAT> </FILEREF> diff --git a/security/nss/macbuild/NSSCommon.h b/security/nss/macbuild/NSSCommon.h index 3b3a94c31..83a54d7e3 100755 --- a/security/nss/macbuild/NSSCommon.h +++ b/security/nss/macbuild/NSSCommon.h @@ -2,4 +2,5 @@ #define NSPR20 1 #define MP_API_COMPATIBLE 1 -#define NSS_3_4_CODE 1 /* Remove this when we start building NSS 4.0 by default */
\ No newline at end of file +#define NSS_3_4_CODE 1 /* Remove this when we start building NSS 4.0 by default */ +#define SHLIB_SUFFIX "shlb" diff --git a/security/nss/manifest.mn b/security/nss/manifest.mn index a72cac1ea..97533f29e 100644 --- a/security/nss/manifest.mn +++ b/security/nss/manifest.mn @@ -33,8 +33,8 @@ CORE_DEPTH = .. DEPTH = .. -IMPORTS = nspr20/v4.1.2 \ - dbm/DBM_1_61_RC1 \ +IMPORTS = nspr20/v4.2 \ + dbm/DBM_1_61_RTM \ $(NULL) RELEASE = security diff --git a/security/nss/tests/cert/cert.sh b/security/nss/tests/cert/cert.sh index cfb3d16df..05e602d38 100755 --- a/security/nss/tests/cert/cert.sh +++ b/security/nss/tests/cert/cert.sh @@ -34,7 +34,7 @@ ######################################################################## # -# mozilla/security/nss/tests/cert/cert.sh +# mozilla/security/nss/tests/cert/rcert.sh # # Certificate generating and handeling for NSS QA, can be included # multiple times from all.sh and the individual scripts @@ -85,7 +85,7 @@ cert_init() cert_log() ###################### write the cert_status file { - #echo "$SCRIPTNAME $*" + echo "$SCRIPTNAME $*" echo $* >>${CERT_LOG_FILE} } @@ -98,7 +98,7 @@ cert_log() ###################### write the cert_status file ######################################################################### noise() { - netstat >> ${NOISE_FILE} 2>&1 + #netstat >> ${NOISE_FILE} 2>&1 date >> ${NOISE_FILE} 2>&1 } @@ -129,6 +129,9 @@ certu() else html_passed "<TR><TD>${CU_ACTION}" fi + + # echo "Contine?" + # cat > /dev/null return $RET } @@ -140,6 +143,7 @@ cert_init_cert() CERTDIR="$1" CERTNAME="$2" CERTSERIAL="$3" + DOMAIN="$4" if [ ! -d "${CERTDIR}" ]; then mkdir -p "${CERTDIR}" @@ -149,6 +153,11 @@ cert_init_cert() cd "${CERTDIR}" CERTDIR="." + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${DOMAIN}" + fi + noise } @@ -166,9 +175,9 @@ hw_acc() echo "modutil -add rainbow -libfile /usr/lib/libcryptoki22.so " - echo " -dbdir . 2>&1 " + echo " -dbdir ${PROFILEDIR} 2>&1 " echo | modutil -add rainbow -libfile /usr/lib/libcryptoki22.so \ - -dbdir . 2>&1 + -dbdir ${PROFILEDIR} 2>&1 if [ "$?" -ne 0 ]; then echo "modutil -add rainbow failed in `pwd`" HW_ACC_RET=1 @@ -177,10 +186,10 @@ hw_acc() echo "modutil -add ncipher " echo " -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so " - echo " -dbdir . 2>&1 " + echo " -dbdir ${PROFILEDIR} 2>&1 " echo | modutil -add ncipher \ -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so \ - -dbdir . 2>&1 + -dbdir ${PROFILEDIR} 2>&1 if [ "$?" -ne 0 ]; then echo "modutil -add ncipher failed in `pwd`" HW_ACC_RET=`expr $HW_ACC_RET + 2` @@ -204,16 +213,16 @@ hw_acc() ######################################################################## cert_create_cert() { - cert_init_cert "$1" "$2" "$3" + cert_init_cert "$1" "$2" "$3" "$4" CU_ACTION="Initializing ${CERTNAME}'s Cert DB" - certu -N -d "${CERTDIR}" -f "${R_PWFILE}" 2>&1 + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 if [ "$RET" -ne 0 ]; then return $RET fi hw_acc CU_ACTION="Import Root CA for $CERTNAME" - certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${CERTDIR}" \ + certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ -i "${R_CADIR}/root.cert" 2>&1 if [ "$RET" -ne 0 ]; then return $RET @@ -234,20 +243,20 @@ cert_add_cert() CU_ACTION="Generate Cert Request for $CERTNAME" CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" - certu -R -d "${CERTDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 if [ "$RET" -ne 0 ]; then return $RET fi CU_ACTION="Sign ${CERTNAME}'s Request" - certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${R_CADIR}" \ + certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 if [ "$RET" -ne 0 ]; then return $RET fi CU_ACTION="Import $CERTNAME's Cert" - certu -A -n "$CERTNAME" -t "u,u,u" -d "${CERTDIR}" -f "${R_PWFILE}" \ + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -i "${CERTNAME}.cert" 2>&1 if [ "$RET" -ne 0 ]; then return $RET @@ -267,23 +276,23 @@ cert_all_CA() echo nss > ${PWFILE} ALL_CU_SUBJECT="CN=NSS Test CA, O=BOGUS NSS, L=Mountain View, ST=California, C=US" - cert_CA $CADIR TestCA -x "CTu,CTu,CTu" + cert_CA $CADIR TestCA -x "CTu,CTu,CTu" ${D_CA} ALL_CU_SUBJECT="CN=NSS Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" - cert_CA $SERVER_CADIR serverCA -x "Cu,Cu,Cu" + cert_CA $SERVER_CADIR serverCA -x "Cu,Cu,Cu" ${D_SERVER_CA} ALL_CU_SUBJECT="CN=NSS Chain1 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" - cert_CA $SERVER_CADIR chain-1-serverCA "-c serverCA" "u,u,u" + cert_CA $SERVER_CADIR chain-1-serverCA "-c serverCA" "u,u,u" ${D_SERVER_CA} ALL_CU_SUBJECT="CN=NSS Chain2 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" - cert_CA $SERVER_CADIR chain-2-serverCA "-c chain-1-serverCA" "u,u,u" + cert_CA $SERVER_CADIR chain-2-serverCA "-c chain-1-serverCA" "u,u,u" ${D_SERVER_CA} ALL_CU_SUBJECT="CN=NSS Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" - cert_CA $CLIENT_CADIR clientCA -x "Tu,Cu,Cu" + cert_CA $CLIENT_CADIR clientCA -x "Tu,Cu,Cu" ${D_CLIENT_CA} ALL_CU_SUBJECT="CN=NSS Chain1 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" - cert_CA $CLIENT_CADIR chain-1-clientCA "-c clientCA" "u,u,u" + cert_CA $CLIENT_CADIR chain-1-clientCA "-c clientCA" "u,u,u" ${D_CLIENT_CA} ALL_CU_SUBJECT="CN=NSS Chain2 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" - cert_CA $CLIENT_CADIR chain-2-clientCA "-c chain-1-clientCA" "u,u,u" + cert_CA $CLIENT_CADIR chain-2-clientCA "-c chain-1-clientCA" "u,u,u" ${D_CLIENT_CA} rm $CLIENT_CADIR/root.cert $SERVER_CADIR/root.cert # root.cert in $CLIENT_CADIR and in $SERVER_CADIR is the one of the last @@ -300,6 +309,7 @@ cert_CA() NICKNAME=$2 SIGNER=$3 TRUSTARG=$4 + DOMAIN=$5 echo "$SCRIPTNAME: Creating a CA Certificate $NICKNAME ==========================" @@ -309,10 +319,14 @@ cert_CA() cd ${CUR_CADIR} pwd + LPROFILE=. + if [ -n "${MULTIACCESS_DBM}" ]; then + LPROFILE="multiaccess:${DOMAIN}" + fi if [ "$SIGNER" = "-x" ] ; then # self signed -> create DB CU_ACTION="Creating CA Cert DB" - certu -N -d . -f ${R_PWFILE} 2>&1 + certu -N -d ${LPROFILE} -f ${R_PWFILE} 2>&1 if [ "$RET" -ne 0 ]; then Exit 5 "Fatal - failed to create CA $NICKNAME " fi @@ -324,7 +338,7 @@ cert_CA() # CU_ACTION="Creating CA Cert $NICKNAME " CU_SUBJECT=$ALL_CU_SUBJECT - certu -S -n $NICKNAME -t $TRUSTARG -v 60 $SIGNER -d . -1 -2 -5 \ + certu -S -n $NICKNAME -t $TRUSTARG -v 60 $SIGNER -d ${LPROFILE} -1 -2 -5 \ -f ${R_PWFILE} -z ${R_NOISE_FILE} 2>&1 <<CERTSCRIPT 5 9 @@ -340,13 +354,14 @@ n CERTSCRIPT if [ "$RET" -ne 0 ]; then + echo "return value is $RET" Exit 6 "Fatal - failed to create CA cert" fi ################# Exporting Root Cert ################################### # CU_ACTION="Exporting Root Cert" - certu -L -n $NICKNAME -r -d . -o root.cert + certu -L -n $NICKNAME -r -d ${LPROFILE} -o root.cert if [ "$RET" -ne 0 ]; then Exit 7 "Fatal - failed to export root cert" fi @@ -361,43 +376,44 @@ cert_smime_client() CERTFAILED=0 echo "$SCRIPTNAME: Creating Client CA Issued Certificates ==============" - cert_create_cert ${ALICEDIR} "Alice" 3 - cert_create_cert ${BOBDIR} "Bob" 4 + cert_create_cert ${ALICEDIR} "Alice" 3 ${D_ALICE} + cert_create_cert ${BOBDIR} "Bob" 4 ${D_BOB} echo "$SCRIPTNAME: Creating Dave's Certificate -------------------------" - cert_init_cert "${DAVEDIR}" Dave 5 - cp ${CADIR}/*.db . - hw_acc + cert_create_cert "${DAVEDIR}" Dave 5 ${D_DAVE} + #echo "************* Copying CA files to ${SERVERDIR}" + #cp ${CADIR}/*.db . + #hw_acc ######################################################################### # - cd ${CERTDIR} - CU_ACTION="Creating ${CERTNAME}'s Server Cert" - CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" - certu -S -n "${CERTNAME}" -c "TestCA" -t "u,u,u" -m "$CERTSERIAL" -d . \ - -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 + #cd ${CERTDIR} + #CU_ACTION="Creating ${CERTNAME}'s Server Cert" + #CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" + #certu -S -n "${CERTNAME}" -c "TestCA" -t "u,u,u" -m "$CERTSERIAL" \ + # -d ${PROFILEDIR} -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 - CU_ACTION="Export Dave's Cert" - cd ${DAVEDIR} - certu -L -n "Dave" -r -d . -o Dave.cert + #CU_ACTION="Export Dave's Cert" + #cd ${DAVEDIR} + #certu -L -n "Dave" -r -d ${P_R_DAVE} -o Dave.cert ################# Importing Certificates for S/MIME tests ############### # echo "$SCRIPTNAME: Importing Certificates ==============================" CU_ACTION="Import Alices's cert into Bob's db" - certu -E -t "p,p,p" -d ${R_BOBDIR} -f ${R_PWFILE} \ + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ -i ${R_ALICEDIR}/Alice.cert 2>&1 CU_ACTION="Import Bob's cert into Alice's db" - certu -E -t "p,p,p" -d ${R_ALICEDIR} -f ${R_PWFILE} \ + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ -i ${R_BOBDIR}/Bob.cert 2>&1 CU_ACTION="Import Dave's cert into Alice's DB" - certu -E -t "p,p,p" -d ${R_ALICEDIR} -f ${R_PWFILE} \ + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ -i ${R_DAVEDIR}/Dave.cert 2>&1 CU_ACTION="Import Dave's cert into Bob's DB" - certu -E -t "p,p,p" -d ${R_BOBDIR} -f ${R_PWFILE} \ + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ -i ${R_DAVEDIR}/Dave.cert 2>&1 if [ "$CERTFAILED" != 0 ] ; then @@ -419,26 +435,26 @@ cert_extended_ssl() echo " of a chain of CA's which are not in the same database============" echo "Server Cert" - cert_init_cert ${EXT_SERVERDIR} "${HOSTADDR}" 1 + cert_init_cert ${EXT_SERVERDIR} "${HOSTADDR}" 1 ${D_EXT_SERVER} CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" - certu -N -d "${CERTDIR}" -f "${R_PWFILE}" 2>&1 + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 CU_ACTION="Generate Cert Request for $CERTNAME (ext)" CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" - certu -R -d "${CERTDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request (ext)" cp ${CERTDIR}/req ${SERVER_CADIR} - certu -C -c "chain-2-serverCA" -m "$CERTSERIAL" -v 60 -d "${SERVER_CADIR}" \ + certu -C -c "chain-2-serverCA" -m "$CERTSERIAL" -v 60 -d "${P_SERVER_CADIR}" \ -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" - certu -A -n "$CERTNAME" -t "u,u,u" -d "${CERTDIR}" -f "${R_PWFILE}" \ + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -i "${CERTNAME}.cert" 2>&1 CU_ACTION="Import Client Root CA -t T,, for $CERTNAME (ext.)" - certu -A -n "clientCA" -t "T,," -f "${R_PWFILE}" -d "${CERTDIR}" \ + certu -A -n "clientCA" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ -i "${CLIENT_CADIR}/clientCA.ca.cert" 2>&1 echo "Importing all the server's own CA chain into the servers DB" for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ; @@ -450,30 +466,30 @@ cert_extended_ssl() T="-t u,u,u" fi CU_ACTION="Import $N CA $T for $CERTNAME (ext.) " - certu -A -n $N $T -f "${R_PWFILE}" -d "${CERTDIR}" \ + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ -i "${CA}" 2>&1 done #============ echo "Client Cert" - cert_init_cert ${EXT_CLIENTDIR} ExtendedSSLUser 1 + cert_init_cert ${EXT_CLIENTDIR} ExtendedSSLUser 1 ${D_EXT_CLIENT} CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" - certu -N -d "${CERTDIR}" -f "${R_PWFILE}" 2>&1 + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 CU_ACTION="Generate Cert Request for $CERTNAME (ext)" CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" - certu -R -d "${CERTDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request (ext)" cp ${CERTDIR}/req ${CLIENT_CADIR} - certu -C -c "chain-2-clientCA" -m "$CERTSERIAL" -v 60 -d "${CLIENT_CADIR}" \ + certu -C -c "chain-2-clientCA" -m "$CERTSERIAL" -v 60 -d "${P_CLIENT_CADIR}" \ -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" - certu -A -n "$CERTNAME" -t "u,u,u" -d "${CERTDIR}" -f "${R_PWFILE}" \ + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -i "${CERTNAME}.cert" 2>&1 CU_ACTION="Import Server Root CA -t C,C,C for $CERTNAME (ext.)" - certu -A -n "serverCA" -t "C,C,C" -f "${R_PWFILE}" -d "${CERTDIR}" \ + certu -A -n "serverCA" -t "C,C,C" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ -i "${SERVER_CADIR}/serverCA.ca.cert" 2>&1 echo "Importing all the client's own CA chain into the servers DB" for CA in `find ${CLIENT_CADIR} -name "?*.ca.cert"` ; @@ -485,7 +501,7 @@ cert_extended_ssl() T="-t u,u,u" fi CU_ACTION="Import $N CA $T for $CERTNAME (ext.)" - certu -A -n $N $T -f "${R_PWFILE}" -d "${CERTDIR}" \ + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ -i "${CA}" 2>&1 done if [ "$CERTFAILED" != 0 ] ; then @@ -504,17 +520,20 @@ cert_ssl() # CERTFAILED=0 echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" - cert_create_cert ${CLIENTDIR} "TestUser" 6 + cert_create_cert ${CLIENTDIR} "TestUser" 6 ${D_CLIENT} echo "$SCRIPTNAME: Creating Server CA Issued Certificate for \\" echo " ${HOSTADDR} ------------------------------------" - cert_init_cert ${SERVERDIR} "${HOSTADDR}" 1 - cp ${CADIR}/*.db . - hw_acc - CU_ACTION="Creating ${CERTNAME}'s Server Cert" - CU_SUBJECT="CN=${CERTNAME}, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" - certu -S -n "${CERTNAME}" -c "TestCA" -t "Pu,Pu,Pu" -d . -f "${R_PWFILE}" \ - -z "${R_NOISE_FILE}" -v 60 2>&1 + cert_create_cert ${SERVERDIR} "${HOSTADDR}" 1 ${D_SERVER} + certu -M -n "TestCA" -t "TC,TC,TC" -d ${PROFILEDIR} +# cert_init_cert ${SERVERDIR} "${HOSTADDR}" 1 ${D_SERVER} +# echo "************* Copying CA files to ${SERVERDIR}" +# cp ${CADIR}/*.db . +# hw_acc +# CU_ACTION="Creating ${CERTNAME}'s Server Cert" +# CU_SUBJECT="CN=${CERTNAME}, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" +# certu -S -n "${CERTNAME}" -c "TestCA" -t "Pu,Pu,Pu" -d ${PROFILEDIR} \ +# -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 if [ "$CERTFAILED" != 0 ] ; then cert_log "ERROR: SSL failed $RET" @@ -533,6 +552,10 @@ cert_stresscerts() CERTDIR="$CLIENTDIR" cd "${CERTDIR}" + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${D_CLIENT}" + fi CERTFAILED=0 echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" @@ -560,13 +583,13 @@ cert_fips() { CERTFAILED=0 echo "$SCRIPTNAME: Creating FIPS 140-1 DSA Certificates ==============" - cert_init_cert "${FIPSDIR}" "FIPS PUB 140-1 Test Certificate" 1000 + cert_init_cert "${FIPSDIR}" "FIPS PUB 140-1 Test Certificate" 1000 "${D_FIPS}" CU_ACTION="Initializing ${CERTNAME}'s Cert DB" - certu -N -d "${CERTDIR}" -f "${R_FIPSPWFILE}" 2>&1 + certu -N -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" 2>&1 echo "$SCRIPTNAME: Enable FIPS mode on database -----------------------" - modutil -dbdir ${CERTDIR} -fips true 2>&1 <<MODSCRIPT + modutil -dbdir ${PROFILEDIR} -fips true 2>&1 <<MODSCRIPT y MODSCRIPT CU_ACTION="Enable FIPS mode on database for ${CERTNAME}" @@ -579,7 +602,7 @@ MODSCRIPT CU_ACTION="Generate Certificate for ${CERTNAME}" CU_SUBJECT="CN=${CERTNAME}, E=fips@bogus.com, O=BOGUS NSS, OU=FIPS PUB 140-1, L=Mountain View, ST=California, C=US" - certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${CERTDIR}" -f "${R_FIPSPWFILE}" -k dsa -m ${CERTSERIAL} -z "${R_NOISE_FILE}" 2>&1 + certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -k dsa -m ${CERTSERIAL} -z "${R_NOISE_FILE}" 2>&1 if [ "$RET" -eq 0 ]; then cert_log "SUCCESS: FIPS passed" fi diff --git a/security/nss/tests/cipher/cipher.sh b/security/nss/tests/cipher/cipher.sh index 63acc897c..a90a9dbe4 100755 --- a/security/nss/tests/cipher/cipher.sh +++ b/security/nss/tests/cipher/cipher.sh @@ -65,12 +65,17 @@ cipher_init() CIPHERDIR=${HOSTDIR}/cipher CIPHERTESTDIR=${QADIR}/../cmd/bltest + D_CIPHER="Cipher.$version" CIPHER_TXT=${QADIR}/cipher/cipher.txt mkdir -p ${CIPHERDIR} cd ${CIPHERTESTDIR} + P_CIPHER=. + if [ -n "${MULTIACCESS_DBM}" ]; then + P_CIPHER="multiaccess:${D_CIPHER}" + fi } ############################## cipher_main ############################# @@ -84,9 +89,9 @@ cipher_main() PARAM=`echo $PARAM | sed -e "s/_-/ -/g"` TESTNAME=`echo $TESTNAME | sed -e "s/_/ /g"` echo "$SCRIPTNAME: $TESTNAME --------------------------------" - echo "bltest -T -m $PARAM -d ." + echo "bltest -T -m $PARAM -d ${P_CIPHER}" - bltest -T -m $PARAM -d . + bltest -T -m $PARAM -d ${P_CIPHER} html_msg $? $EXP_RET "$TESTNAME" fi done diff --git a/security/nss/tests/clean_tbx b/security/nss/tests/clean_tbx index 74d83de4f..4de955576 100755 --- a/security/nss/tests/clean_tbx +++ b/security/nss/tests/clean_tbx @@ -22,9 +22,9 @@ $PASSED_TBX_KEEP_HOURS=2; $IF_TBX_KEEP_HOURS=2; $PASSED_NEWER_DIRS=2; $IF_NEWER_DIRS=2; -$verbose = 0; +$verbose = 1; -$TBX_TESTDIR="/share/builds/mccrel/nss/nsstip/tinderbox/tests_results/security"; +$TBX_TESTDIR="/share/builds/mccrel3/nss/nsstip/tinderbox/tests_results/security"; $FTP_STAGE="/u/sonmi/tmp/ftp_stage/tinderbox"; @tbx_dirs = (); @@ -34,7 +34,7 @@ $ePASSED_TBX_KEEP=$PASSED_TBX_KEEP_HOURS*60*60; $eIF_TBX_KEEP=$IF_TBX_KEEP_HOURS*60*60; $eNOT_FAILED_TBX_KEEP=$NOT_FAILED_TBX_KEEP_HOURS*60*60; -$days, $hours, $minutes, $seconds; +$year, $month, $days, $hours, $minutes, $seconds; $efulldate=0; $fulldate=0; @@ -56,8 +56,6 @@ debug ("$seconds, $minutes, $hours, $days, $month, $year"); $enow = timelocal(localtime); - - sub debug; sub warning; sub error; @@ -65,7 +63,6 @@ sub msg; sub init; sub check_tbx_dirs; - sub check_tbx_dirs { my $platform_idx=0; # counts directories per platform, newest @@ -141,6 +138,7 @@ sub rm_tbx() debug ("DELETING $tbx_dir... (@_[0]) "); system("rm -rf $TBX_TESTDIR/$tbx_dir"); +#debug ("rm -rf $TBX_TESTDIR/$tbx_dir"); } diff --git a/security/nss/tests/common/init.sh b/security/nss/tests/common/init.sh index 343ff134b..529cbef02 100644 --- a/security/nss/tests/common/init.sh +++ b/security/nss/tests/common/init.sh @@ -359,6 +359,19 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then FIPSP12PWFILE=${TMP}/tests.fipsp12pw.$$ FIPSCERTNICK="FIPS_PUB_140-1_Test_Certificate" + # domains to handle ipc based access to databases + D_CA="TestCA.$version" + D_ALICE="Alice.$version" + D_BOB="Bob.$version" + D_DAVE="Dave.$version" + D_SERVER_CA="ServerCA.$version" + D_CLIENT_CA="ClientCA.$version" + D_SERVER="Server.$version" + D_CLIENT="Client.$version" + D_FIPS="FIPS.$version" + D_EXT_SERVER="ExtendedServer.$version" + D_EXT_CLIENT="ExtendedClient.$version" + # we need relative pathnames of these files abd directories, since our # tools can't handle the unix style absolut pathnames on cygnus @@ -371,6 +384,33 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then R_EXT_SERVERDIR=../ext_server R_EXT_CLIENTDIR=../ext_client + # + # profiles are either paths or domains depending on the setting of + # MULTIACCESS_DBM + # + P_R_CADIR=${R_CADIR} + P_R_ALICEDIR=${R_ALICEDIR} + P_R_BOBDIR=${R_BOBDIR} + P_R_DAVEDIR=${R_DAVEDIR} + P_R_SERVERDIR=${R_SERVERDIR} + P_R_CLIENTDIR=${R_CLIENTDIR} + P_R_EXT_SERVERDIR=${R_EXT_SERVERDIR} + P_R_EXT_CLIENTDIR=${R_EXT_CLIENTDIR} + P_SERVER_CADIR=${SERVER_CADIR} + P_CLIENT_CADIR=${CLIENT_CADIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + P_R_CADIR="multiaccess:${D_CA}" + P_R_ALICEDIR="multiaccess:${D_ALICE}" + P_R_BOBDIR="multiaccess:${D_BOB}" + P_R_DAVEDIR="multiaccess:${D_DAVE}" + P_R_SERVERDIR="multiaccess:${D_SERVER}" + P_R_CLIENTDIR="multiaccess:${D_CLIENT}" + P_R_EXT_SERVERDIR="multiaccess:${D_EXT_SERVER}" + P_R_EXT_CLIENTDIR="multiaccess:${D_EXT_CLIENT}" + P_SERVER_CADIR="multiaccess:${D_SERVER_CA}" + P_CLIENT_CADIR="multiaccess:${D_CLIENT_CA}" + fi + R_PWFILE=../tests.pw.$$ R_NOISE_FILE=../tests_noise.$$ diff --git a/security/nss/tests/fips/fips.sh b/security/nss/tests/fips/fips.sh index 8e4fcb1f0..cf94db945 100755 --- a/security/nss/tests/fips/fips.sh +++ b/security/nss/tests/fips/fips.sh @@ -76,8 +76,13 @@ fips_init() COPYDIR=${FIPSDIR}/copydir R_FIPSDIR=../fips + P_R_FIPSDIR=../fips R_COPYDIR=../fips/copydir + if [ -n "${MULTIACCESS_DBM}" ]; then + P_R_FIPSDIR="multiaccess:${D_FIPS}" + fi + mkdir -p ${FIPSDIR} mkdir -p ${COPYDIR} @@ -91,73 +96,73 @@ fips_init() fips_140_1() { echo "$SCRIPTNAME: List the FIPS module certificates -----------------" - echo "certutil -d ${R_FIPSDIR} -L" - certutil -d ${R_FIPSDIR} -L 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -L" + certutil -d ${P_R_FIPSDIR} -L 2>&1 html_msg $? 0 "List the FIPS module certificates (certutil -L)" echo "$SCRIPTNAME: List the FIPS module keys -------------------------" - echo "certutil -d ${R_FIPSDIR} -K -f ${R_FIPSPWFILE}" - certutil -d ${R_FIPSDIR} -K -f ${R_FIPSPWFILE} 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -K -f ${R_FIPSPWFILE}" + certutil -d ${P_R_FIPSDIR} -K -f ${R_FIPSPWFILE} 2>&1 html_msg $? 0 "List the FIPS module keys (certutil -K)" echo "$SCRIPTNAME: Attempt to list FIPS module keys with incorrect password" - echo "certutil -d ${R_FIPSDIR} -K -f ${FIPSBADPWFILE}" - certutil -d ${R_FIPSDIR} -K -f ${FIPSBADPWFILE} 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -K -f ${FIPSBADPWFILE}" + certutil -d ${P_R_FIPSDIR} -K -f ${FIPSBADPWFILE} 2>&1 RET=$? html_msg $RET 255 "Attempt to list FIPS module keys with incorrect password (certutil -K)" echo "certutil -K returned $RET" echo "$SCRIPTNAME: Validate the certificate --------------------------" - echo "certutil -d ${R_FIPSDIR} -V -n ${FIPSCERTNICK} -u SR -e -f ${R_FIPSPWFILE}" - certutil -d ${R_FIPSDIR} -V -n ${FIPSCERTNICK} -u SR -e -f ${R_FIPSPWFILE} + echo "certutil -d ${P_R_FIPSDIR} -V -n ${FIPSCERTNICK} -u SR -e -f ${R_FIPSPWFILE}" + certutil -d ${P_R_FIPSDIR} -V -n ${FIPSCERTNICK} -u SR -e -f ${R_FIPSPWFILE} html_msg $? 0 "Validate the certificate (certutil -V -e)" echo "$SCRIPTNAME: Export the certificate and key as a PKCS#12 file --" - echo "pk12util -d ${R_FIPSDIR} -o fips140.p12 -n ${FIPSCERTNICK} -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE}" - pk12util -d ${R_FIPSDIR} -o fips140.p12 -n ${FIPSCERTNICK} -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE} 2>&1 + echo "pk12util -d ${P_R_FIPSDIR} -o fips140.p12 -n ${FIPSCERTNICK} -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE}" + pk12util -d ${P_R_FIPSDIR} -o fips140.p12 -n ${FIPSCERTNICK} -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE} 2>&1 html_msg $? 0 "Export the certificate and key as a PKCS#12 file (pk12util -o)" echo "$SCRIPTNAME: Export the certificate as a DER-encoded file ------" - echo "certutil -d ${R_FIPSDIR} -L -n ${FIPSCERTNICK} -r -o fips140.crt" - certutil -d ${R_FIPSDIR} -L -n ${FIPSCERTNICK} -r -o fips140.crt 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -L -n ${FIPSCERTNICK} -r -o fips140.crt" + certutil -d ${P_R_FIPSDIR} -L -n ${FIPSCERTNICK} -r -o fips140.crt 2>&1 html_msg $? 0 "Export the certificate as a DER (certutil -L -r)" echo "$SCRIPTNAME: List the FIPS module certificates -----------------" - echo "certutil -d ${R_FIPSDIR} -L" - certutil -d ${R_FIPSDIR} -L 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -L" + certutil -d ${P_R_FIPSDIR} -L 2>&1 html_msg $? 0 "List the FIPS module certificates (certutil -L)" echo "$SCRIPTNAME: Delete the certificate and key from the FIPS module" - echo "certutil -d ${R_FIPSDIR} -F -n ${FIPSCERTNICK} -f ${R_FIPSPWFILE}" - certutil -d ${R_FIPSDIR} -F -n ${FIPSCERTNICK} -f ${R_FIPSPWFILE} 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -F -n ${FIPSCERTNICK} -f ${R_FIPSPWFILE}" + certutil -d ${P_R_FIPSDIR} -F -n ${FIPSCERTNICK} -f ${R_FIPSPWFILE} 2>&1 html_msg $? 0 "Delete the certificate and key from the FIPS module (certutil -D)" echo "$SCRIPTNAME: List the FIPS module certificates -----------------" - echo "certutil -d ${R_FIPSDIR} -L" - certutil -d ${R_FIPSDIR} -L 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -L" + certutil -d ${P_R_FIPSDIR} -L 2>&1 html_msg $? 0 "List the FIPS module certificates (certutil -L)" echo "$SCRIPTNAME: List the FIPS module keys." - echo "certutil -d ${R_FIPSDIR} -K -f ${R_FIPSPWFILE}" - certutil -d ${R_FIPSDIR} -K -f ${R_FIPSPWFILE} 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -K -f ${R_FIPSPWFILE}" + certutil -d ${P_R_FIPSDIR} -K -f ${R_FIPSPWFILE} 2>&1 # certutil -K now returns a failure if no keys are found. This verifies that # our delete succeded. html_msg $? 255 "List the FIPS module keys (certutil -K)" echo "$SCRIPTNAME: Import the certificate and key from the PKCS#12 file" - echo "pk12util -d ${R_FIPSDIR} -i fips140.p12 -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE}" - pk12util -d ${R_FIPSDIR} -i fips140.p12 -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE} 2>&1 + echo "pk12util -d ${P_R_FIPSDIR} -i fips140.p12 -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE}" + pk12util -d ${P_R_FIPSDIR} -i fips140.p12 -w ${R_FIPSP12PWFILE} -k ${R_FIPSPWFILE} 2>&1 html_msg $? 0 "Import the certificate and key from the PKCS#12 file (pk12util -i)" echo "$SCRIPTNAME: List the FIPS module certificates -----------------" - echo "certutil -d ${R_FIPSDIR} -L" - certutil -d ${R_FIPSDIR} -L 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -L" + certutil -d ${P_R_FIPSDIR} -L 2>&1 html_msg $? 0 "List the FIPS module certificates (certutil -L)" echo "$SCRIPTNAME: List the FIPS module keys --------------------------" - echo "certutil -d ${R_FIPSDIR} -K -f ${R_FIPSPWFILE}" - certutil -d ${R_FIPSDIR} -K -f ${R_FIPSPWFILE} 2>&1 + echo "certutil -d ${P_R_FIPSDIR} -K -f ${R_FIPSPWFILE}" + certutil -d ${P_R_FIPSDIR} -K -f ${R_FIPSPWFILE} 2>&1 html_msg $? 0 "List the FIPS module keys (certutil -K)" } diff --git a/security/nss/tests/header b/security/nss/tests/header index a0b2cc13f..b5d117b2d 100644 --- a/security/nss/tests/header +++ b/security/nss/tests/header @@ -208,7 +208,7 @@ export BC_RELEASE EARLY_EXIT=TRUE #before the report file has been created, causes Exit to #create it -UX_D0=/share/builds/mccrel/nss +UX_D0=/share/builds/mccrel3/nss ################################### glob_init ########################## # global shell function, main initialisation function @@ -568,9 +568,9 @@ init_dirs() set_daily_build_dirs if [ -z "${BCDIST}" ] ; then - #BCDIST=/share/builds/mccrel/nss/${BC_MASTER}/mozilla/dist + #BCDIST=/share/builds/mccrel3/nss/${BC_MASTER}/mozilla/dist BCDIST=${NSS_VER_DIR}/../${BC_MASTER}/mozilla/dist - if [ ! -d $BCDIST ] ; then + if [ ! -d $BCDIST -a `basename $0` != jssqa ] ; then ask "Backward compatibility directory $BCDIST does not exist, continue" "y" "n" || Exit fi fi @@ -602,7 +602,7 @@ init_dirs() TESTSCRIPTDIR=${MOZILLA_ROOT}/security/nss/tests fi - if [ ! -d $TESTSCRIPTDIR ] ; then + if [ ! -d $TESTSCRIPTDIR -a `basename $0` != jssqa ] ; then if [ "$O_WIN" = "ON" -a "$WIN_WAIT_FOREVER" = "ON" ] then WaitForever $TESTSCRIPTDIR/all.sh 1 @@ -871,23 +871,21 @@ eval_opts() -*) glob_usage "Error: Can't handle option $1" ;; - ?*) + tip|3.|3..) NSSVER=$1 - if [ -z "$NSSVER" ] - then - NSSVER="tip" - Debug "NSS Version: Parameters missing - defaulting to tip!" - else - BUILDDATE=$2 - if [ -z "$BUILDDATE" ] - then - BUILDDATE=`date +%m%d` - Debug "Builddate: Parameters missing - defaulting to today!" - else - shift - fi + if [ -z "$NSSVER" ] ; then + glob_usage "Error: illegal parameter" + fi + ;; + [01][0-9][0123][0-9]) + BUILDDATE=$1 + if [ -z "$BUILDDATE" ] ; then + glob_usage "Error: illegal parameter" fi ;; + ?*) + glob_usage "Error: Can't handle parameter $1" + ;; esac shift done @@ -895,17 +893,18 @@ eval_opts() if [ -z "$PORT" -a "$O_TBX" = "ON" ] ; then PORT=8444 export PORT + if [ -z "$NSSVER" ] ; then + NSSVER="tip" + Debug "NSS Version: Parameters missing - defaulting to tip!" + fi + elif [ -z "$NSSVER" ] ; then + NSSVER="341" + Debug "NSS Version: Parameters missing - defaulting to 341!" fi - if [ -z "$BUILDDATE" ] - then + if [ -z "$BUILDDATE" ] ; then BUILDDATE=`date +%m%d` Debug "Builddate: Parameters missing - defaulting to today!" fi - if [ -z "$NSSVER" ] - then - NSSVER="tip" - Debug "NSS Version: Parameters missing - defaulting to tip!" - fi Debug "Builddate $BUILDDATE NssVersion $NSSVER" export BUILDDATE NSSVER diff --git a/security/nss/tests/jssdir b/security/nss/tests/jssdir index 6c9fd355e..1609fbfcf 100755 --- a/security/nss/tests/jssdir +++ b/security/nss/tests/jssdir @@ -17,7 +17,7 @@ else if ( "$QAYEAR" == "" ) then endif -setenv JSS_VER_DIR /share/builds/mccrel/jss/jss$JSSVER +setenv JSS_VER_DIR /share/builds/mccrel3/jss/jss$JSSVER setenv NTDIST ${JSS_VER_DIR}/builds/${QAYEAR}${BUILDDATE}.1/blowfish_NT4.0_Win95/mozilla/dist setenv UXDIST ${JSS_VER_DIR}/builds/${QAYEAR}${BUILDDATE}.1/booboo_Solaris8/mozilla/dist setenv TESTSCRIPTDIR ${JSS_VER_DIR}/builds/${QAYEAR}${BUILDDATE}.1/booboo_Solaris8/mozilla/security/jss/tests diff --git a/security/nss/tests/nssdir b/security/nss/tests/nssdir index 296872217..884c299f5 100755 --- a/security/nss/tests/nssdir +++ b/security/nss/tests/nssdir @@ -17,7 +17,7 @@ else if ( "$QAYEAR" == "" ) then endif -setenv NSS_VER_DIR /share/builds/mccrel/nss/nss$NSSVER +setenv NSS_VER_DIR /share/builds/mccrel3/nss/nss$NSSVER setenv NTDIST ${NSS_VER_DIR}/builds/${QAYEAR}${BUILDDATE}.1/blowfish_NT4.0_Win95/mozilla/dist setenv UXDIST ${NSS_VER_DIR}/builds/${QAYEAR}${BUILDDATE}.1/booboo_Solaris8/mozilla/dist setenv TESTSCRIPTDIR ${NSS_VER_DIR}/builds/${QAYEAR}${BUILDDATE}.1/booboo_Solaris8/mozilla/security/nss/tests diff --git a/security/nss/tests/qa_stage b/security/nss/tests/qa_stage index f818c605a..f0960c845 100755 --- a/security/nss/tests/qa_stage +++ b/security/nss/tests/qa_stage @@ -46,7 +46,7 @@ qa_stage_init() Echo "Init..." DAYBUILD=${QAYEAR}${BUILDDATE}.${BUILDNUMBER} - NSS_D0=/share/builds/mccrel/nss + NSS_D0=/share/builds/mccrel3/nss NSS_VER_DIR=${NSS_D0}/nss${NSSVER} NTDIST=${NSS_VER_DIR}/builds/${DAYBUILD}/blowfish_NT4.0_Win95/mozilla/dist UXDIST=${NSS_VER_DIR}/builds/${DAYBUILD}/booboo_Solaris8/mozilla/dist @@ -130,7 +130,7 @@ qa_stage_tbx() Echo "find from $TBX_FIND_FROM" for w in `find $TBX_FIND_FROM -name "result.html"` do - if [ ! -d $TBX_STAGE/`dirname $w` ] ; then + if [ ! -d "$TBX_STAGE/`dirname $w`" ] ; then mkdir -p $TBX_STAGE/`dirname $w` fi rm $TBX_STAGE/$w 2>/dev/null @@ -294,11 +294,15 @@ else TARPARAM=cvf fi -if [ "$DO_DQA" = "ON" && "$DO_TBX" = "ON" ] ; then + +if [ "$DO_DQA" = "ON" -a "$DO_TBX" = "ON" ] ; then + Echo "tar $TARPARAM all.tar daily_qa tinderbox" tar $TARPARAM all.tar daily_qa tinderbox elif [ "$DO_DQA" = "ON" ] ; then + Echo "tar $TARPARAM all.tar daily_qa" tar $TARPARAM all.tar daily_qa else + Echo "tar $TARPARAM all.tar tinderbox" tar $TARPARAM all.tar tinderbox fi gzip all.tar diff --git a/security/nss/tests/qa_stat b/security/nss/tests/qa_stat index 231a3b68b..aa3e4bb88 100755 --- a/security/nss/tests/qa_stat +++ b/security/nss/tests/qa_stat @@ -239,7 +239,7 @@ etscape]"> <h2> <a href="http://tinderbox.mozilla.org/showbuilds.cgi?tree=NSS">Tinderbox</a ><br> -<a href="http://cindercone.red.iplanet.com/share/builds/mccrel/nss/nsstip/tinderbox/tests_results/security/">Tinderbox QA result</a><br> +<a href="http://cindercone.red.iplanet.com/share/builds/mccrel3/nss/nsstip/tinderbox/tests_results/security/">Tinderbox QA result</a><br> <a href="ftp://ftp.mozilla.org/pub/security/nss/daily_qa">Mozilla Daily NSS QA result</a></h2> diff --git a/security/nss/tests/sdr/sdr.sh b/security/nss/tests/sdr/sdr.sh index a36066589..36c0f40ae 100755 --- a/security/nss/tests/sdr/sdr.sh +++ b/security/nss/tests/sdr/sdr.sh @@ -71,10 +71,16 @@ sdr_init() T2="The quick brown fox jumped over the lazy dog" SDRDIR=${HOSTDIR}/SDR + D_SDR="SDR.$version" if [ ! -d ${SDRDIR} ]; then mkdir -p ${SDRDIR} fi + PROFILE=. + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILE="multiaccess:${D_SDR}" + fi + cd ${SDRDIR} html_head "SDR Tests" } @@ -85,23 +91,23 @@ sdr_init() sdr_main() { echo "$SCRIPTNAME: Creating an SDR key/Encrypt" - echo "sdrtest -d . -o ${VALUE1} -t Test1" - sdrtest -d . -o ${VALUE1} -t Test1 + echo "sdrtest -d ${PROFILE} -o ${VALUE1} -t Test1" + sdrtest -d ${PROFILE} -o ${VALUE1} -t Test1 html_msg $? 0 "Creating SDR Key" echo "$SCRIPTNAME: SDR Encrypt - Second Value" - echo "sdrtest -d . -o ${VALUE2} -t '${T2}'" - sdrtest -d . -o ${VALUE2} -t "${T2}" + echo "sdrtest -d ${PROFILE} -o ${VALUE2} -t '${T2}'" + sdrtest -d ${PROFILE} -o ${VALUE2} -t "${T2}" html_msg $? 0 "Encrypt - Value 2" echo "$SCRIPTNAME: Decrypt - Value 1" - echo "sdrtest -d . -i ${VALUE1} -t Test1" - sdrtest -d . -i ${VALUE1} -t Test1 + echo "sdrtest -d ${PROFILE} -i ${VALUE1} -t Test1" + sdrtest -d ${PROFILE} -i ${VALUE1} -t Test1 html_msg $? 0 "Decrypt - Value 1" echo "$SCRIPTNAME: Decrypt - Value 2" - echo "sdrtest -d . -i ${VALUE2} -t ${T2}" - sdrtest -d . -i ${VALUE2} -t "${T2}" + echo "sdrtest -d ${PROFILE} -i ${VALUE2} -t ${T2}" + sdrtest -d ${PROFILE} -i ${VALUE2} -t "${T2}" html_msg $? 0 "Decrypt - Value 2" } diff --git a/security/nss/tests/set_environment b/security/nss/tests/set_environment index 829d6c6d9..5a3515cca 100644 --- a/security/nss/tests/set_environment +++ b/security/nss/tests/set_environment @@ -33,6 +33,7 @@ if [ "$os_name" != "Windows_95" -a \ then PATH=.:$HOME/bin:/tools/ns/bin:/bin:/usr/bin:/usr/sbin:/usr/ccs/bin:/usr/dist/local/exe:/usr/bin/X11:/usr/audio/bin:/u/sonmi/bin:$PATH JAVA_HOME="D:/i386/jdk1.2.2" + JAVA_HOME14="R:/jdk/1.4.0/WINNT" fi CVSROOT=:pserver:svbld@redcvs.red.iplanet.com:/m/src @@ -60,6 +61,7 @@ if [ "$os_name" = "HP-UX" ] then PATH=$PATH:/usr/local/bin:/opt/aCC/bin:/usr/local/bin/audio:/tools/ns/bin:/etc:/usr/contrib/bin:/usr/contrib/bin/X11:/usr/local/hpux/bin:/nfs/iapp1/hphome/bin:/etc:/u/svbld/bin/HP/perl/bin JAVA_HOME="/share/builds/components/cms_jdk/HP-UX/1.2.2.04" + JAVA_HOME14=$JAVA_HOME # JAVA_HOME="/share/builds/components/cms_jdk/HP-UX/1.3.0.00" elif [ "$os_name" = "SunOS" ] then @@ -71,10 +73,12 @@ then then #PATH=/usr/ucb:/opt/usr/local/bin:$PATH JAVA_HOME="/usr/java1.2" + JAVA_HOME14=/share/builds/components/jdk/1.4.0/SunOS_x86 PATH=".:/usr/dist/share/forte_dev_i386,v6.2/SUNWspro/bin:/opt/usr/local/perl5/bin:/opt/SUNWspro/bin:/opt/usr/local/bin:/bin:/usr/bin:/usr/sbin:/usr/ccs/bin:/usr/dist/local/exe:/usr/ccs/bin:/usr/ucb/bin:/usr/ucb:/opt/SUNWwabi/bin:/usr/local/bin:/tools/ns/bin:/etc:/tools/contrib/bin" else PATH=/usr/ucb:$PATH JAVA_HOME="/share/builds/components/jdk/1.2.2/SunOS" + JAVA_HOME14=/share/builds/components/jdk/1.4.0/SunOS64 PATH=/tools/ns/bin:$PATH:/opt/SUNWspro/bin:/usr/bin/X11:/usr/openwin/bin:/usr/openwin/demo if [ "$os_version" = "5.8" -o "$os_version" = "5.7" -o \ @@ -93,11 +97,13 @@ then PATH=$PATH:/tools/ns/bin:/usr/local/bin:/etc:/usr/bsd MANPATH=/tools/ns/man:/usr/local/man JAVA_HOME="/share/builds/components/jdk/1.2.2/IRIX" + JAVA_HOME14=$JAVA_HOME elif [ "$os_name" = "IRIX64" ] then PATH=$PATH:/tools/ns/bin:/usr/local/bin:/etc:/usr/bsd MANPATH=/tools/ns/man:/usr/local/man JAVA_HOME="/share/builds/components/jdk/1.2.2/IRIX" + JAVA_HOME14=$JAVA_HOME elif [ "$os_name" = "Linux" ] then PATH=/lib:/usr/lib:/bin:/sbin:/usr/bin:/usr/sbin:$PATH @@ -107,16 +113,19 @@ then BEFORE_CONTEXT_GREP="--before-context=10" AFTER_CONTEXT_GREP="--after-context=3" JAVA_HOME="/share/builds/components/jdk/1.2.2/Linux" + JAVA_HOME14=/share/builds/components/jdk/1.4.0/Linux elif [ "$os_name" = "AIX" ] then PATH=$PATH:/tools/contrib/bin:/usr/local/bin TERM=vt100 export TERM JAVA_HOME="/share/builds/components/cms_jdk/AIX/1.3.0" + JAVA_HOME14=$JAVA_HOME elif [ "$os_name" = "OSF1" ] then PATH=$PATH:/usr/local/bin JAVA_HOME="/share/builds/components/jdk/1.2.2/OSF1" + JAVA_HOME14=$JAVA_HOME fi if [ "$os_name" = "IRIX" ] @@ -218,6 +227,8 @@ system=`uname -n` # name of this system. JAVAC=$JAVA_HOME/bin/javac JAVA=$JAVA_HOME/bin/java +JAVAC14=$JAVA_HOME14/bin/javac +JAVA14=$JAVA_HOME14/bin/java #JAVA=$JAVA_HOME/jre/bin/java -export JAVAC JAVA JAVA_HOME +export JAVAC JAVA JAVA_HOME JAVAC14 JAVA_HOME14 JAVA14 diff --git a/security/nss/tests/smime/smime.sh b/security/nss/tests/smime/smime.sh index 040ced05c..64726e558 100755 --- a/security/nss/tests/smime/smime.sh +++ b/security/nss/tests/smime/smime.sh @@ -89,12 +89,12 @@ smime_main() { echo "$SCRIPTNAME: Signing Attached Message ------------------------------" - echo "cmsutil -S -N Alice -i alice.txt -d ${R_ALICEDIR} -p nss -o alice.sig" - cmsutil -S -N Alice -i alice.txt -d ${R_ALICEDIR} -p nss -o alice.sig + echo "cmsutil -S -N Alice -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.sig" + cmsutil -S -N Alice -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.sig html_msg $? 0 "Create Signature Alice" "." - echo "cmsutil -D -i alice.sig -d ${R_BOBDIR} -o alice.data1" - cmsutil -D -i alice.sig -d ${R_BOBDIR} -o alice.data1 + echo "cmsutil -D -i alice.sig -d ${P_R_BOBDIR} -o alice.data1" + cmsutil -D -i alice.sig -d ${P_R_BOBDIR} -o alice.data1 html_msg $? 0 "Decode Alice's Signature" "." echo "diff alice.txt alice.data1" @@ -102,14 +102,14 @@ smime_main() html_msg $? 0 "Compare Decoded Signature and Original" "." echo "$SCRIPTNAME: Enveloped Data Tests ------------------------------" - echo "cmsutil -E -r bob@bogus.com -i alice.txt -d ${R_ALICEDIR} -p nss \\" + echo "cmsutil -E -r bob@bogus.com -i alice.txt -d ${P_R_ALICEDIR} -p nss \\" echo " -o alice.env" - cmsutil -E -r bob@bogus.com -i alice.txt -d ${R_ALICEDIR} -p nss -o alice.env + cmsutil -E -r bob@bogus.com -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.env html_msg $? 0 "Create Enveloped Data Alice" "." - echo "cmsutil -D -i alice.env -d ${R_BOBDIR} -p nss -o alice.data1" - cmsutil -D -i alice.env -d ${R_BOBDIR} -p nss -o alice.data1 + echo "cmsutil -D -i alice.env -d ${P_R_BOBDIR} -p nss -o alice.data1" + cmsutil -D -i alice.env -d ${P_R_BOBDIR} -p nss -o alice.data1 html_msg $? 0 "Decode Enveloped Data Alice" "." echo "diff alice.txt alice.data1" @@ -118,9 +118,9 @@ smime_main() # multiple recip echo "$SCRIPTNAME: Testing multiple recipients ------------------------------" - echo "cmsutil -E -i alicecc.txt -d ${R_ALICEDIR} -o alicecc.env \\" + echo "cmsutil -E -i alicecc.txt -d ${P_R_ALICEDIR} -o alicecc.env \\" echo " -r bob@bogus.com,dave@bogus.com" - cmsutil -E -i alice.txt -d ${R_ALICEDIR} -o alicecc.env \ + cmsutil -E -i alice.txt -d ${P_R_ALICEDIR} -o alicecc.env \ -r bob@bogus.com,dave@bogus.com ret=$? html_msg $ret 0 "Create Multiple Recipients Enveloped Data Alice" "." @@ -130,21 +130,21 @@ smime_main() cp -r ${R_ALICEDIR} ${R_ALICEDIR}.trouble while [ $i -lt 100 ] ; do echo "will attempt to list the certs in the db `expr 100 - $i` more times" - echo "certutil -L -d ${R_ALICEDIR}" - certutil -L -d ${R_ALICEDIR} - echo "certutil -L -d ${R_ALICEDIR} -n dave@bogus.com" - certutil -L -d ${R_ALICEDIR} -n dave@bogus.com + echo "certutil -L -d ${P_R_ALICEDIR}" + certutil -L -d ${P_R_ALICEDIR} + echo "certutil -L -d ${P_R_ALICEDIR} -n dave@bogus.com" + certutil -L -d ${P_R_ALICEDIR} -n dave@bogus.com sleep 30 i=`expr $i + 1` done fi - echo "cmsutil -D -i alicecc.env -d ${R_BOBDIR} -p nss -o alice.data2" - cmsutil -D -i alicecc.env -d ${R_BOBDIR} -p nss -o alice.data2 + echo "cmsutil -D -i alicecc.env -d ${P_R_BOBDIR} -p nss -o alice.data2" + cmsutil -D -i alicecc.env -d ${P_R_BOBDIR} -p nss -o alice.data2 html_msg $? 0 "Decode Multiple Recipients Enveloped Data Alice by Bob" "." - echo "cmsutil -D -i alicecc.env -d ${R_DAVEDIR} -p nss -o alice.data2" - cmsutil -D -i alicecc.env -d ${R_DAVEDIR} -p nss -o alice.data3 + echo "cmsutil -D -i alicecc.env -d ${P_R_DAVEDIR} -p nss -o alice.data2" + cmsutil -D -i alicecc.env -d ${P_R_DAVEDIR} -p nss -o alice.data3 html_msg $? 0 "Decode Multiple Recipients Enveloped Data Alice by Dave" "." diff alice.txt alice.data2 @@ -155,24 +155,24 @@ smime_main() echo "$SCRIPTNAME: Sending CERTS-ONLY Message ------------------------------" echo "cmsutil -O -r \"Alice,bob@bogus.com,dave@bogus.com\" \\" - echo " -d ${R_ALICEDIR} > co.der" - cmsutil -O -r "Alice,bob@bogus.com,dave@bogus.com" -d ${R_ALICEDIR} > co.der + echo " -d ${P_R_ALICEDIR} > co.der" + cmsutil -O -r "Alice,bob@bogus.com,dave@bogus.com" -d ${P_R_ALICEDIR} > co.der html_msg $? 0 "Create Certs-Only Alice" "." - echo "cmsutil -D -i co.der -d ${R_BOBDIR}" - cmsutil -D -i co.der -d ${R_BOBDIR} + echo "cmsutil -D -i co.der -d ${P_R_BOBDIR}" + cmsutil -D -i co.der -d ${P_R_BOBDIR} html_msg $? 0 "Verify Certs-Only by CA" "." echo "$SCRIPTNAME: Encrypted-Data Message ---------------------------------" - echo "cmsutil -C -i alice.txt -e alicehello.env -d ${R_ALICEDIR} \\" + echo "cmsutil -C -i alice.txt -e alicehello.env -d ${P_R_ALICEDIR} \\" echo " -r \"bob@bogus.com\" > alice.enc" - cmsutil -C -i alice.txt -e alicehello.env -d ${R_ALICEDIR} \ + cmsutil -C -i alice.txt -e alicehello.env -d ${P_R_ALICEDIR} \ -r "bob@bogus.com" > alice.enc html_msg $? 0 "Create Encrypted-Data" "." - echo "cmsutil -D -i alice.enc -d ${R_BOBDIR} -e alicehello.env -p nss \\" + echo "cmsutil -D -i alice.enc -d ${P_R_BOBDIR} -e alicehello.env -p nss \\" echo " -o alice.data2" - cmsutil -D -i alice.enc -d ${R_BOBDIR} -e alicehello.env -p nss -o alice.data2 + cmsutil -D -i alice.enc -d ${P_R_BOBDIR} -e alicehello.env -p nss -o alice.data2 html_msg $? 0 "Decode Encrypted-Data" "." diff alice.txt alice.data2 diff --git a/security/nss/tests/ssl/ssl.sh b/security/nss/tests/ssl/ssl.sh index 464319030..2db98b457 100755 --- a/security/nss/tests/ssl/ssl.sh +++ b/security/nss/tests/ssl/ssl.sh @@ -127,13 +127,15 @@ is_selfserv_alive() ######################################################################## wait_for_selfserv() { - echo "tstclnt -p ${PORT} -h ${HOST} -q -d . < ${REQUEST_FILE} " + echo "tstclnt -p ${PORT} -h ${HOST} -q " + echo " -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} \\" #echo "tstclnt -q started at `date`" - tstclnt -p ${PORT} -h ${HOST} -q -d . < ${REQUEST_FILE} + tstclnt -p ${PORT} -h ${HOST} -q -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} if [ $? -ne 0 ]; then html_failed "<TR><TD> Wait for Server " - echo "RETRY: tstclnt -p ${PORT} -h ${HOST} -q -d . < ${REQUEST_FILE}" - tstclnt -p ${PORT} -h ${HOST} -q -d . < ${REQUEST_FILE} + echo "RETRY: tstclnt -p ${PORT} -h ${HOST} -q \\" + echo " -d ${P_R_CLIENTDIR} < ${REQUEST_FILE}" + tstclnt -p ${PORT} -h ${HOST} -q -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} elif [ sparam = "-c ABCDEFabcdefghijklmnvy" ] ; then # "$1" = "cov" ] ; then html_passed "<TR><TD> Wait for Server" fi @@ -165,15 +167,15 @@ start_selfserv() echo "$SCRIPTNAME: $testname ----" fi sparam=`echo $sparam | sed -e 's;_; ;g'` - echo "selfserv -D -p ${PORT} -d ${R_SERVERDIR} -n ${HOSTADDR} \\" + echo "selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} \\" echo " -w nss ${sparam} -i ${R_SERVERPID} $verbose &" echo "selfserv started at `date`" if [ ${fileout} -eq 1 ]; then - selfserv -D -p ${PORT} -d ${R_SERVERDIR} -n ${HOSTADDR} \ + selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} \ -w nss ${sparam} -i ${R_SERVERPID} $verbose \ > ${SERVEROUTFILE} 2>&1 & else - selfserv -D -p ${PORT} -d ${R_SERVERDIR} -n ${HOSTADDR} \ + selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} \ -w nss ${sparam} -i ${R_SERVERPID} $verbose & fi wait_for_selfserv @@ -211,11 +213,12 @@ ssl_cov() is_selfserv_alive echo "tstclnt -p ${PORT} -h ${HOST} -c ${param} ${TLS_FLAG} \\" - echo " -f -d . < ${REQUEST_FILE}" + echo " -f -d ${P_R_CLIENTDIR} < ${REQUEST_FILE}" rm ${TMP}/$HOST.tmp.$$ 2>/dev/null tstclnt -p ${PORT} -h ${HOST} -c ${param} ${TLS_FLAG} -f \ - -d . < ${REQUEST_FILE} >${TMP}/$HOST.tmp.$$ 2>&1 + -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 ret=$? cat ${TMP}/$HOST.tmp.$$ rm ${TMP}/$HOST.tmp.$$ 2>/dev/null @@ -240,11 +243,12 @@ ssl_auth() cparam=`echo $cparam | sed -e 's;_; ;g' -e "s/TestUser/$USER_NICKNAME/g" ` start_selfserv - echo "tstclnt -p ${PORT} -h ${HOST} -f -d . ${cparam} \\" - echo " < ${REQUEST_FILE}" + echo "tstclnt -p ${PORT} -h ${HOST} -f -d ${P_R_CLIENTDIR} \\" + echo " ${cparam} < ${REQUEST_FILE}" rm ${TMP}/$HOST.tmp.$$ 2>/dev/null tstclnt -p ${PORT} -h ${HOST} -f ${cparam} \ - -d . < ${REQUEST_FILE} >${TMP}/$HOST.tmp.$$ 2>&1 + -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 ret=$? cat ${TMP}/$HOST.tmp.$$ rm ${TMP}/$HOST.tmp.$$ 2>/dev/null @@ -279,10 +283,11 @@ ssl_stress() ps -ef | grep selfserv fi - echo "strsclnt -q -p ${PORT} -d . -w nss $cparam $verbose \\" - echo " ${HOSTADDR}" + echo "strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} -w nss $cparam \\" + echo " $verbose ${HOSTADDR}" echo "strsclnt started at `date`" - strsclnt -q -p ${PORT} -d . -w nss $cparam $verbose ${HOSTADDR} + strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} -w nss $cparam \ + $verbose ${HOSTADDR} ret=$? echo "strsclnt completed at `date`" html_msg $ret $value "${testname}" @@ -323,6 +328,8 @@ if [ -z "$DO_REM_ST" -a -z "$DO_DIST_ST" ] ; then CLIENTDIR=$EXT_CLIENTDIR R_SERVERDIR=$R_EXT_SERVERDIR R_CLIENTDIR=$R_EXT_CLIENTDIR + P_R_SERVERDIR=$P_R_EXT_SERVERDIR + P_R_CLIENTDIR=$P_R_EXT_CLIENTDIR USER_NICKNAME=ExtendedSSLUser NORM_EXT="Extended test" cd ${CLIENTDIR} diff --git a/security/nss/tests/ssl/ssl_dist_stress.sh b/security/nss/tests/ssl/ssl_dist_stress.sh index b418f80d7..e9b328e4b 100755 --- a/security/nss/tests/ssl/ssl_dist_stress.sh +++ b/security/nss/tests/ssl/ssl_dist_stress.sh @@ -198,7 +198,7 @@ ssl_ds_rem_stress() CONTINUE=$MAX_CERT while [ $CONTINUE -ge $MIN_CERT ] do - echo "strsclnt -D -p ${PORT} -d . -w nss -c 1 $verbose " + echo "strsclnt -D -p ${PORT} -d ${P_R_CLIENTDIR} -w nss -c 1 $verbose " echo " -n TestUser$CONTINUE ${HOSTADDR} #`uname -n`" strsclnt -D -p ${PORT} -d . -w nss -c 1 $verbose \ -n "TestUser$CONTINUE" ${HOSTADDR} & @@ -289,9 +289,9 @@ ssl_ds_dist_stress() sleep 500 # give the clients time to finish #FIXME ADJUST echo "GET /stop HTTP/1.0\n\n" > stdin.txt #check to make sure it has /r/n - echo "tstclnt -h $HOSTADDR -p 8443 -d ${CLIENTDIR} -n TestUser0 " + echo "tstclnt -h $HOSTADDR -p 8443 -d ${P_R_CLIENTDIR} -n TestUser0 " echo " -w nss -f < stdin.txt" - tstclnt -h $HOSTADDR -p 8443 -d ${CLIENTDIR} -n TestUser0 \ + tstclnt -h $HOSTADDR -p 8443 -d ${P_R_CLIENTDIR} -n TestUser0 \ -w nss -f < stdin.txt html_msg 0 0 "${testname}" diff --git a/security/nss/tests/tools/tools.sh b/security/nss/tests/tools/tools.sh index bfab403d5..b301fc72b 100644 --- a/security/nss/tests/tools/tools.sh +++ b/security/nss/tests/tools/tools.sh @@ -82,6 +82,10 @@ tools_init() R_TOOLSDIR=../tools R_COPYDIR=../tools/copydir + P_R_COPYDIR=${R_COPYDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + P_R_COPYDIR="multiaccess:Tools.$version" + fi mkdir -p ${TOOLSDIR} mkdir -p ${COPYDIR} @@ -97,17 +101,17 @@ tools_init() tools_p12() { echo "$SCRIPTNAME: Exporting Alice's email cert & key------------------" - echo "pk12util -o Alice.p12 -n \"Alice\" -d ${R_ALICEDIR} -k ${R_PWFILE} \\" + echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" echo " -w ${R_PWFILE}" - pk12util -o Alice.p12 -n "Alice" -d ${R_ALICEDIR} -k ${R_PWFILE} \ + pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ -w ${R_PWFILE} 2>&1 ret=$? html_msg $ret 0 "Exporting Alice's email cert & key (pk12util -o)" check_tmpfile echo "$SCRIPTNAME: Importing Alice's email cert & key -----------------" - echo "pk12util -i Alice.p12 -d ${R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" - pk12util -i Alice.p12 -d ${R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 + echo "pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" + pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 ret=$? html_msg $ret 0 "Importing Alice's email cert & key (pk12util -i)" check_tmpfile @@ -131,8 +135,8 @@ check_tmpfile() tools_sign() { echo "$SCRIPTNAME: Create objsign cert -------------------------------" - echo "signtool -G \"objectsigner\" -d ${R_ALICEDIR} -p \"nss\"" - signtool -G "objsigner" -d ${R_ALICEDIR} -p "nss" 2>&1 <<SIGNSCRIPT + echo "signtool -G \"objectsigner\" -d ${P_R_ALICEDIR} -p \"nss\"" + signtool -G "objsigner" -d ${P_R_ALICEDIR} -p "nss" 2>&1 <<SIGNSCRIPT y TEST MOZ @@ -145,19 +149,20 @@ SIGNSCRIPT html_msg $? 0 "Create objsign cert (signtool -G)" echo "$SCRIPTNAME: Signing a set of files ----------------------------" - echo "signtool -Z nojs.jar -d ${R_ALICEDIR} -p \"nss\" -k objsigner \\" + echo "signtool -Z nojs.jar -d ${P_R_ALICEDIR} -p \"nss\" -k objsigner \\" echo " ${R_TOOLSDIR}/html" - signtool -Z nojs.jar -d ${R_ALICEDIR} -p "nss" -k objsigner ${R_TOOLSDIR}/html + signtool -Z nojs.jar -d ${P_R_ALICEDIR} -p "nss" -k objsigner \ + ${R_TOOLSDIR}/html html_msg $? 0 "Signing a set of files (signtool -Z)" echo "$SCRIPTNAME: Listing signed files in jar ----------------------" - echo "signtool -v nojs.jar -d ${R_ALICEDIR} -p nss -k objsigner" - signtool -v nojs.jar -d ${R_ALICEDIR} -p nss -k objsigner + echo "signtool -v nojs.jar -d ${P_R_ALICEDIR} -p nss -k objsigner" + signtool -v nojs.jar -d ${P_R_ALICEDIR} -p nss -k objsigner html_msg $? 0 "Listing signed files in jar (signtool -v)" echo "$SCRIPTNAME: Show who signed jar ------------------------------" - echo "signtool -w nojs.jar -d ${R_ALICEDIR}" - signtool -w nojs.jar -d ${R_ALICEDIR} + echo "signtool -w nojs.jar -d ${P_R_ALICEDIR}" + signtool -w nojs.jar -d ${P_R_ALICEDIR} html_msg $? 0 "Show who signed jar (signtool -w)" } |