summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorian.mcgreer%sun.com <devnull@localhost>2001-11-28 16:23:51 +0000
committerian.mcgreer%sun.com <devnull@localhost>2001-11-28 16:23:51 +0000
commit1f76ef2659e4785f0411c1dc7c70c0aa36af7b7c (patch)
treeeca905b0b3bea53d2c8314c807567912b5b31c3a /security
parentba8cfdd8b7d0dfa4ab81f470228cf11a0d13ef8d (diff)
downloadnss-hg-1f76ef2659e4785f0411c1dc7c70c0aa36af7b7c.tar.gz
land changes for handling temporary and cached certs in 3.4
* separate trust object from cert object * move handling of cryptoki objects into libdev * implement digest in libdev (for trust object indexing) * fixes in cache implementation; connect cache to 3.4 certs * implement CERT_NewTempCertificate via crypto context
Diffstat (limited to 'security')
-rw-r--r--security/nss/lib/base/base.h20
-rw-r--r--security/nss/lib/base/hash.c2
-rw-r--r--security/nss/lib/base/item.c13
-rw-r--r--security/nss/lib/base/list.c32
-rw-r--r--security/nss/lib/certdb/stanpcertdb.c38
-rw-r--r--security/nss/lib/certhigh/certvfy.c10
-rw-r--r--security/nss/lib/dev/ckhelper.c4
-rw-r--r--security/nss/lib/dev/dev.h140
-rw-r--r--security/nss/lib/dev/devmod.c6
-rw-r--r--security/nss/lib/dev/devobject.c950
-rw-r--r--security/nss/lib/dev/devt.h47
-rw-r--r--security/nss/lib/dev/devtoken.c402
-rw-r--r--security/nss/lib/dev/manifest.mn7
-rw-r--r--security/nss/lib/dev/nssdevt.h2
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c264
-rw-r--r--security/nss/lib/pki/certificate.c447
-rw-r--r--security/nss/lib/pki/cryptocontext.c60
-rw-r--r--security/nss/lib/pki/pki.h21
-rw-r--r--security/nss/lib/pki/pki3hack.c282
-rw-r--r--security/nss/lib/pki/pki3hack.h5
-rw-r--r--security/nss/lib/pki/pkim.h9
-rw-r--r--security/nss/lib/pki/pkit.h56
-rw-r--r--security/nss/lib/pki/tdcache.c973
-rw-r--r--security/nss/lib/pki/trustdomain.c558
24 files changed, 2630 insertions, 1718 deletions
diff --git a/security/nss/lib/base/base.h b/security/nss/lib/base/base.h
index b7ec1ce24..9523a243b 100644
--- a/security/nss/lib/base/base.h
+++ b/security/nss/lib/base/base.h
@@ -562,6 +562,12 @@ nssItem_Create
const void *data
);
+NSS_EXTERN void
+nssItem_Destroy
+(
+ NSSItem *item
+);
+
NSS_EXTERN NSSItem *
nssItem_Duplicate
(
@@ -831,8 +837,8 @@ nssList_Destroy
nssList *list
);
-NSS_EXTERN PRStatus
-nssList_DestroyElements
+NSS_EXTERN void
+nssList_Clear
(
nssList *list,
nssListElementDestructorFunc destructor
@@ -1005,6 +1011,16 @@ nssListIterator_Finish
*/
NSS_EXTERN nssHash *
+nssHash_Create
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets,
+ PLHashFunction keyHash,
+ PLHashComparator keyCompare,
+ PLHashComparator valueCompare
+);
+
+NSS_EXTERN nssHash *
nssHash_CreatePointer
(
NSSArena *arenaOpt,
diff --git a/security/nss/lib/base/hash.c b/security/nss/lib/base/hash.c
index dd0a61576..39598ddd9 100644
--- a/security/nss/lib/base/hash.c
+++ b/security/nss/lib/base/hash.c
@@ -112,7 +112,7 @@ nss_compare_items(const void *v1, const void *v2)
* nssHash_create
*
*/
-static nssHash *
+NSS_IMPLEMENT nssHash *
nssHash_Create
(
NSSArena *arenaOpt,
diff --git a/security/nss/lib/base/item.c b/security/nss/lib/base/item.c
index 073e437d3..efa9d1200 100644
--- a/security/nss/lib/base/item.c
+++ b/security/nss/lib/base/item.c
@@ -116,6 +116,19 @@ nssItem_Create
return (NSSItem *)NULL;
}
+NSS_IMPLEMENT void
+nssItem_Destroy
+(
+ NSSItem *item
+)
+{
+ nss_ClearErrorStack();
+
+ nss_ZFreeIf(item->data);
+ nss_ZFreeIf(item);
+
+}
+
/*
* nssItem_Duplicate
*
diff --git a/security/nss/lib/base/list.c b/security/nss/lib/base/list.c
index 1037c989f..97eb874f8 100644
--- a/security/nss/lib/base/list.c
+++ b/security/nss/lib/base/list.c
@@ -138,8 +138,17 @@ nssList_Create
NSS_IMPLEMENT PRStatus
nssList_Destroy(nssList *list)
{
- if (list->lock) PZ_DestroyLock(list->lock);
- NSSArena_Destroy(list->arena);
+ PZLock *lock = list->lock;
+ if (list->arena) {
+ NSSArena_Destroy(list->arena);
+ list = NULL;
+ } else {
+ nssList_Clear(list, NULL);
+ }
+ if (lock) {
+ PZ_DestroyLock(lock);
+ }
+ nss_ZFreeIf(list);
return PR_SUCCESS;
}
@@ -162,22 +171,23 @@ nssList_GetCompareFunction(nssList *list)
return list->compareFunc;
}
-NSS_IMPLEMENT PRStatus
-nssList_DestroyElements(nssList *list, nssListElementDestructorFunc destructor)
+NSS_IMPLEMENT void
+nssList_Clear(nssList *list, nssListElementDestructorFunc destructor)
{
PRCList *link;
- nssListElement *node;
+ nssListElement *node, *tmp;
NSSLIST_LOCK_IF(list);
node = list->head;
while (node && list->count > 0) {
- (*destructor)(node->data);
+ if (destructor) (*destructor)(node->data);
link = &node->link;
- node = (nssListElement *)PR_NEXT_LINK(link);
+ tmp = (nssListElement *)PR_NEXT_LINK(link);
PR_REMOVE_LINK(link);
+ nss_ZFreeIf(node);
+ node = tmp;
--list->count;
}
NSSLIST_UNLOCK_IF(list);
- return nssList_Destroy(list);
}
static PRStatus
@@ -271,7 +281,7 @@ nssList_Get(nssList *list, void *data)
NSSLIST_LOCK_IF(list);
node = nsslist_get_matching_element(list, data);
NSSLIST_UNLOCK_IF(list);
- return node->data;
+ return (node) ? node->data : NULL;
}
NSS_IMPLEMENT PRUint32
@@ -286,14 +296,14 @@ nssList_GetArray(nssList *list, void **rvArray, PRUint32 maxElements)
nssListIterator *iter;
void *el;
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;
- if (maxElements > 0 && i == maxElements) break;
+ if (i == maxElements) break;
}
- rvArray[i] = NULL;
nssListIterator_Finish(iter);
nssListIterator_Destroy(iter);
return PR_SUCCESS;
diff --git a/security/nss/lib/certdb/stanpcertdb.c b/security/nss/lib/certdb/stanpcertdb.c
index 6010dd875..c2986e323 100644
--- a/security/nss/lib/certdb/stanpcertdb.c
+++ b/security/nss/lib/certdb/stanpcertdb.c
@@ -116,8 +116,7 @@ CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
/* XXX store it on a writeable token */
goto done;
} else {
- NSSCertificate *c = STAN_GetNSSCertificate(cert);
- ret = STAN_ChangeCertTrust(c, trust);
+ ret = STAN_ChangeCertTrust(cert, trust);
rv = (ret == PR_SUCCESS) ? SECSuccess : SECFailure;
}
done:
@@ -141,7 +140,7 @@ __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
}
if (c->nickname && strcmp(nickname, c->nickname) != 0) {
nss_ZFreeIf(c->nickname);
- c->nickname = nssUTF8_Duplicate((NSSUTF8 *)nickname, c->arena);
+ c->nickname = nssUTF8_Duplicate((NSSUTF8 *)nickname, c->object.arena);
PORT_Free(cert->nickname);
cert->nickname = PORT_Strdup(nickname);
}
@@ -168,6 +167,7 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
char *nickname, PRBool isperm, PRBool copyDER)
{
NSSCertificate *c;
+ NSSCryptoContext *context;
nssDecodedCert *dc;
NSSArena *arena;
CERTCertificate *cc;
@@ -175,13 +175,19 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
if (!arena) {
return NULL;
}
- c = NSSCertificate_Create(arena);
+ c = nss_ZNEW(arena, NSSCertificate);
if (!c) {
goto loser;
}
NSSITEM_FROM_SECITEM(&c->encoding, derCert);
+ c->object.arena = arena;
+ c->object.refCount = 1;
+ c->object.instanceList = nssList_Create(arena, PR_TRUE);
+ c->object.instances = nssList_CreateIterator(c->object.instanceList);
+ /* Forces a decoding of the cert in order to obtain the parts used
+ * below
+ */
cc = STAN_GetCERTCertificate(c);
- c->arena = arena;
nssItem_Create(arena,
&c->issuer, cc->derIssuer.len, cc->derIssuer.data);
nssItem_Create(arena,
@@ -200,12 +206,13 @@ __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
(NSSUTF8 *)cc->emailAddr,
PORT_Strlen(cc->emailAddr));
}
- c->trustDomain = handle;
- cc->dbhandle = handle;
- nssTrustDomain_AddCertsToCache(handle, &c, 1);
- cc->istemp = 1;
- cc->isperm = 0;
-
+ context = STAN_GetDefaultCryptoContext();
+ NSSCryptoContext_ImportCertificate(context, c);
+ /* This is a hack to work around the fact that an instance of the cert
+ * doesn't really exist until the import
+ */
+ cc->nssCertificate = NULL;
+ cc = STAN_GetCERTCertificate(c);
return cc;
loser:
nssArena_Destroy(arena);
@@ -363,10 +370,13 @@ CERT_DestroyCertificate(CERTCertificate *cert)
CERT_UnlockCertRefCount(cert);
if ( ( refCount == 0 ) && !cert->keepSession ) {
PRArenaPool *arena = cert->arena;
- if ( cert->istemp ) {
- /* uncache the cert ? */
- }
/* delete the NSSCertificate */
+ NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
+ NSSCertificate *tmp = STAN_GetNSSCertificate(cert);
+ if (tmp) {
+ nssTrustDomain_RemoveCertFromCache(td, tmp);
+ NSSCertificate_Destroy(tmp);
+ }
/* zero cert before freeing. Any stale references to this cert
* after this point will probably cause an exception. */
PORT_Memset(cert, 0, sizeof *cert);
diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c
index 107d9dd2b..bd43be1b4 100644
--- a/security/nss/lib/certhigh/certvfy.c
+++ b/security/nss/lib/certhigh/certvfy.c
@@ -417,9 +417,13 @@ loser:
nss_ZFreeIf(nssTime);
if (status == PR_SUCCESS) {
/* if it's a root, the chain will only have one cert */
- NSSCertificate *issuer = chain[1] ? chain[1] : chain[0];
- CERTCertificate *rvc = STAN_GetCERTCertificate(issuer);
- return rvc;
+ if (!chain[1]) {
+ /* need to dupe since caller expects new cert */
+ return CERT_DupCertificate(cert);
+ } else {
+ /* this is the only instance */
+ return STAN_GetCERTCertificate(chain[1]);
+ }
}
return NULL;
#endif
diff --git a/security/nss/lib/dev/ckhelper.c b/security/nss/lib/dev/ckhelper.c
index f417f3625..8f1d200fb 100644
--- a/security/nss/lib/dev/ckhelper.c
+++ b/security/nss/lib/dev/ckhelper.c
@@ -35,10 +35,6 @@
static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#endif /* DEBUG */
-#ifndef PKIT_H
-#include "pkit.h"
-#endif /* PKIT_H */
-
#ifndef DEV_H
#include "dev.h"
#endif /* DEV_H */
diff --git a/security/nss/lib/dev/dev.h b/security/nss/lib/dev/dev.h
index 4386bcd3a..48ce1d230 100644
--- a/security/nss/lib/dev/dev.h
+++ b/security/nss/lib/dev/dev.h
@@ -64,10 +64,6 @@ static const char DEV_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
* |-----------|---> NSSSlot <--> NSSToken
*/
-#ifndef DEVT_H
-#include "devt.h"
-#endif /* DEVT_H */
-
PR_BEGIN_EXTERN_C
NSS_EXTERN NSSModule *
@@ -248,16 +244,24 @@ nssToken_GetName
NSSToken *tok
);
-/* Given a raw attribute template, import an object
- * (certificate, public key, private key, symmetric key)
- */
-NSS_EXTERN CK_OBJECT_HANDLE
-nssToken_ImportObject
+NSS_EXTERN PRStatus
+nssToken_ImportCertificate
(
NSSToken *tok,
nssSession *sessionOpt,
- CK_ATTRIBUTE_PTR objectTemplate,
- CK_ULONG otsize
+ NSSCertificate *cert,
+ NSSTrustDomain *td,
+ NSSCryptoContext *cc
+);
+
+NSS_EXTERN PRStatus
+nssToken_ImportTrust
+(
+ NSSToken *tok,
+ nssSession *sessionOpt,
+ NSSTrust *trust,
+ NSSTrustDomain *trustDomain,
+ NSSCryptoContext *cryptoContext
);
NSS_EXTERN NSSPublicKey *
@@ -280,39 +284,111 @@ nssToken_GenerateSymmetricKey
NSS_EXTERN PRStatus
nssToken_DeleteStoredObject
(
+ nssCryptokiInstance *instance
+);
+
+NSS_EXTERN NSSTrust *
+nssToken_FindTrustForCert
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSCertificate *c
+);
+
+NSS_EXTERN PRStatus
+nssToken_TraverseCertificates
+(
NSSToken *tok,
nssSession *sessionOpt,
- CK_OBJECT_HANDLE object
+ nssTokenCertSearch *search
+);
+
+NSS_EXTERN PRStatus
+nssToken_TraverseCertificatesBySubject
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSDER *subject,
+ nssTokenCertSearch *search
+);
+
+NSS_EXTERN PRStatus
+nssToken_TraverseCertificatesByNickname
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSUTF8 *name,
+ nssTokenCertSearch *search
+);
+
+NSS_EXTERN PRStatus
+nssToken_TraverseCertificatesByEmail
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSASCII7 *email,
+ nssTokenCertSearch *search
);
-NSS_EXTERN CK_OBJECT_HANDLE
-nssToken_FindObjectByTemplate
+NSS_EXTERN NSSCertificate *
+nssToken_FindCertificateByIssuerAndSerialNumber
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSDER *issuer,
+ NSSDER *serial
+);
+
+NSS_EXTERN NSSCertificate *
+nssToken_FindCertificateByEncodedCertificate
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSBER *encodedCertificate
+);
+
+NSS_EXTERN NSSTrust *
+nssToken_FindTrustForCert
+(
+ NSSToken *token,
+ nssSession *session,
+ NSSCertificate *c
+);
+
+NSS_EXTERN NSSItem *
+nssToken_Digest
(
NSSToken *tok,
nssSession *sessionOpt,
- CK_ATTRIBUTE_PTR cktemplate,
- CK_ULONG ctsize
+ NSSAlgorithmAndParameters *ap,
+ NSSItem *data,
+ NSSItem *rvOpt,
+ NSSArena *arenaOpt
);
NSS_EXTERN PRStatus
-nssToken_TraverseCertificatesByTemplate
+nssToken_BeginDigest
(
NSSToken *tok,
nssSession *sessionOpt,
- nssList *cachedList,
- CK_ATTRIBUTE_PTR cktemplate,
- CK_ULONG ctsize,
- PRStatus (*callback)(NSSCertificate *c, void *arg),
- void *arg
+ NSSAlgorithmAndParameters *ap
);
NSS_EXTERN PRStatus
-nssToken_TraverseCertificates
+nssToken_ContinueDigest
(
NSSToken *tok,
nssSession *sessionOpt,
- PRStatus (*callback)(NSSCertificate *c, void *arg),
- void *arg
+ NSSItem *item
+);
+
+NSS_EXTERN NSSItem *
+nssToken_FinishDigest
+(
+ NSSToken *tok,
+ nssSession *sessionOpt,
+ NSSItem *rvOpt,
+ NSSArena *arenaOpt
);
NSS_EXTERN PRStatus
@@ -342,9 +418,17 @@ nssSession_IsReadWrite
nssSession *s
);
-#ifdef DEBUG
-void nssModule_Debug(NSSModule *m);
-#endif
+NSS_EXTERN NSSAlgorithmAndParameters *
+NSSAlgorithmAndParameters_CreateSHA1Digest
+(
+ NSSArena *arenaOpt
+);
+
+NSS_EXTERN NSSAlgorithmAndParameters *
+NSSAlgorithmAndParameters_CreateMD5Digest
+(
+ NSSArena *arenaOpt
+);
PR_END_EXTERN_C
diff --git a/security/nss/lib/dev/devmod.c b/security/nss/lib/dev/devmod.c
index 301799b77..455d063e8 100644
--- a/security/nss/lib/dev/devmod.c
+++ b/security/nss/lib/dev/devmod.c
@@ -367,12 +367,6 @@ nssModule_TraverseCertificates
void *arg
)
{
- PRUint32 i;
- for (i=0; i<mod->numSlots; i++) {
- /* might as well skip straight to token, right? or is this slot? */
- nssToken_TraverseCertificates(mod->slots[i]->token,
- NULL, callback, arg);
- }
return NULL;
}
diff --git a/security/nss/lib/dev/devobject.c b/security/nss/lib/dev/devobject.c
new file mode 100644
index 000000000..d2bb6df57
--- /dev/null
+++ b/security/nss/lib/dev/devobject.c
@@ -0,0 +1,950 @@
+/*
+ * 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 PKIT_H
+#include "pkit.h"
+#endif /* PKIT_H */
+
+#ifdef NSS_3_4_CODE
+#include "pkim.h" /* for cert decoding */
+#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;
+ 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_ULONG count;
+ 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;
+ 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,
+ OBJECT_STACK_SIZE, &count);
+ if (ckrv != CKR_OK) {
+ nssSession_ExitMonitor(session);
+ goto loser;
+ }
+ if (count == OBJECT_STACK_SIZE) {
+ if (!objectList) {
+ objectArena = NSSArena_Create();
+ objectList = nssList_Create(objectArena, PR_FALSE);
+ }
+ objectStack = nss_ZNEWARRAY(objectArena, CK_OBJECT_HANDLE,
+ OBJECT_STACK_SIZE);
+ nssList_Add(objectList, objectStack);
+ } else {
+ break;
+ }
+ }
+ ckrv = CKAPI(slot)->C_FindObjectsFinal(hSession);
+ nssSession_ExitMonitor(session);
+ if (ckrv != CKR_OK) {
+ goto loser;
+ }
+ if (objectList) {
+ nssListIterator *objects;
+ objects = nssList_CreateIterator(objectList);
+ for (objectStack = (CK_OBJECT_HANDLE *)nssListIterator_Start(objects);
+ objectStack != NULL;
+ objectStack = (CK_OBJECT_HANDLE *)nssListIterator_Next(objects)) {
+ for (i=0; i<count; i++) {
+ cbrv = (*callback)(tok, session, objectStack[i], arg);
+ }
+ }
+ nssListIterator_Finish(objects);
+ count = OBJECT_STACK_SIZE;
+ }
+ for (i=0; i<count; i++) {
+ cbrv = (*callback)(tok, session, startOS[i], arg);
+ }
+ if (objectArena)
+ NSSArena_Destroy(objectArena);
+ return PR_SUCCESS;
+loser:
+ if (objectArena)
+ NSSArena_Destroy(objectArena);
+ return PR_FAILURE;
+}
+
+static PRStatus
+add_object_instance
+(
+ nssPKIObject *object,
+ NSSToken *t,
+ CK_OBJECT_HANDLE h,
+ NSSTrustDomain *td,
+ NSSCryptoContext *cc
+)
+{
+ nssPKIObjectInstance *oi;
+ oi = nss_ZNEW(object->arena, nssPKIObjectInstance);
+ if (!oi) {
+ return PR_FAILURE;
+ }
+ oi->cryptoki.handle = h;
+ oi->cryptoki.token = t;
+ oi->trustDomain = td;
+ oi->cryptoContext = cc;
+ nssList_Add(object->instanceList, oi);
+ return PR_SUCCESS;
+}
+
+#if 0
+#ifdef NSS_3_4_CODE
+static void make_nss3_nickname(NSSCertificate *c)
+{
+ /* In NSS 3.4, the semantic is that nickname = token name + label */
+ PRStatus utf8rv;
+ NSSUTF8 *tokenName;
+ NSSUTF8 *label;
+ char *fullname;
+ PRUint32 len, tlen;
+ tokenName = nssToken_GetName(c->token);
+ label = c->nickname ? c->nickname : c->email;
+ if (!label) return;
+ tlen = nssUTF8_Length(tokenName, &utf8rv); /* token name */
+ tlen += 1; /* : */
+ len = nssUTF8_Length(label, &utf8rv); /* label */
+ len += 1; /* \0 */
+ len += tlen;
+ fullname = nss_ZAlloc(c->arena, len);
+ utf8rv = nssUTF8_CopyIntoFixedBuffer(tokenName, fullname, tlen, ':');
+ utf8rv = nssUTF8_CopyIntoFixedBuffer(label, fullname + tlen,
+ len - tlen, '\0');
+ nss_ZFreeIf(c->nickname);
+ c->nickname = nssUTF8_Create(c->arena,
+ nssStringType_UTF8String,
+ fullname, len);
+}
+#endif
+#endif
+
+static NSSCertificateType
+nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
+{
+ CK_CERTIFICATE_TYPE ckCertType;
+ ckCertType = *((CK_ULONG *)attrib->pValue);
+ switch (ckCertType) {
+ case CKC_X_509:
+ return NSSCertificateType_PKIX;
+ break;
+ default:
+ 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;
+ nssPKIObject *object;
+ 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_LABEL, 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) {
+ goto loser;
+ }
+ object = &rvCert->object;
+ object->arena = arena;
+ object->refCount = 1;
+ object->instanceList = nssList_Create(arena, PR_TRUE);
+ if (!object->instanceList) {
+ goto loser;
+ }
+ object->instances = nssList_CreateIterator(object->instanceList);
+ if (!object->instances) {
+ goto loser;
+ }
+ nssrv = nssCKObject_GetAttributes(handle,
+ cert_template, template_size,
+ arena, session, token->slot);
+ if (nssrv) {
+ 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_UTF8(&cert_template[5], rvCert->nickname);
+ NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[6], &rvCert->subject);
+ NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[7], rvCert->email);
+#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);
+ email = dc->getEmailAddress(dc);
+ if (email) rvCert->email = nssUTF8_Duplicate(email, arena);
+ }
+ /*make_nss3_nickname(rvCert);*/
+#endif
+ return rvCert;
+loser:
+ nssArena_Destroy(arena);
+ return (NSSCertificate *)NULL;
+}
+
+NSS_IMPLEMENT PRStatus
+nssToken_ImportCertificate
+(
+ NSSToken *tok,
+ nssSession *sessionOpt,
+ NSSCertificate *cert,
+ NSSTrustDomain *td,
+ NSSCryptoContext *cc
+)
+{
+ CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
+ CK_OBJECT_HANDLE handle;
+ CK_ATTRIBUTE cert_tmpl[] = {
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_CLASS, NULL, 0 },
+ { CKA_CERTIFICATE_TYPE, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_VALUE, NULL, 0 },
+ { CKA_ISSUER, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_SERIAL_NUMBER, NULL, 0 }
+ };
+ CK_ULONG ctsize = sizeof(cert_tmpl)/sizeof(cert_tmpl[0]);
+ if (td) {
+ /* trust domain == token object */
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 0, &g_ck_true);
+ } else {
+ /* crypto context == session object */
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 0, &g_ck_false);
+ }
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 1, &g_ck_class_cert);
+ NSS_CK_SET_ATTRIBUTE_VAR( cert_tmpl, 2, cert_type);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 3, &cert->id);
+ NSS_CK_SET_ATTRIBUTE_UTF8(cert_tmpl, 4, cert->nickname);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 5, &cert->encoding);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 6, &cert->issuer);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 7, &cert->subject);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_tmpl, 8, &cert->serial);
+ /* Import the certificate onto the token */
+ handle = import_object(tok, sessionOpt, cert_tmpl, ctsize);
+ if (handle == CK_INVALID_HANDLE) {
+ return PR_FAILURE;
+ }
+ return add_object_instance(&cert->object, tok, handle, td, cc);
+}
+
+struct cert_search_index_str
+{
+ NSSDER issuer;
+ NSSDER serial;
+};
+
+static PRBool
+compare_cert_by_issuer_sn(void *a, void *b)
+{
+ NSSCertificate *c = (NSSCertificate *)a;
+ struct cert_search_index_str *csi = (struct cert_search_index_str *)b;
+ return (nssItem_Equal(&c->issuer, &csi->issuer, NULL) &&
+ nssItem_Equal(&c->serial, &csi->serial, NULL));
+}
+
+static PRStatus
+retrieve_cert(NSSToken *t, nssSession *session, CK_OBJECT_HANDLE h, void *arg)
+{
+ PRStatus nssrv;
+ PRBool found;
+ nssTokenCertSearch *search = (nssTokenCertSearch *)arg;
+ NSSCertificate *cert = NULL;
+ struct cert_search_index_str csi;
+ nssListIterator *instances;
+ nssPKIObjectInstance *oi;
+ CK_ATTRIBUTE issuersn_tmpl[] = {
+ { CKA_ISSUER, NULL, 0 },
+ { CKA_SERIAL_NUMBER, NULL, 0 }
+ };
+ CK_ULONG ist_size = sizeof(issuersn_tmpl) / sizeof(issuersn_tmpl[0]);
+ if (search->cached) {
+ nssrv = nssCKObject_GetAttributes(h, issuersn_tmpl, ist_size,
+ NULL, session, t->slot);
+ NSS_CK_ATTRIBUTE_TO_ITEM(&issuersn_tmpl[0], &csi.issuer);
+ NSS_CK_ATTRIBUTE_TO_ITEM(&issuersn_tmpl[1], &csi.serial);
+ cert = (NSSCertificate *)nssList_Get(search->cached, &csi);
+ nss_ZFreeIf(csi.issuer.data);
+ nss_ZFreeIf(csi.serial.data);
+ }
+ found = PR_FALSE;
+ if (cert) {
+ instances = cert->object.instances;
+ for (oi = (nssPKIObjectInstance *)nssListIterator_Start(instances);
+ oi != (nssPKIObjectInstance *)NULL;
+ oi = (nssPKIObjectInstance *)nssListIterator_Next(instances))
+ {
+ if (oi->cryptoki.handle == h && oi->cryptoki.token == t) {
+ found = PR_TRUE;
+ break;
+ }
+ }
+ nssListIterator_Finish(instances);
+ } else {
+ cert = get_token_cert(t, session, h);
+ if (!cert) return PR_FAILURE;
+ }
+ if (!found) {
+ nssrv = add_object_instance(&cert->object, t, h,
+ search->trustDomain,
+ search->cryptoContext);
+ if (nssrv != PR_SUCCESS) {
+ return nssrv;
+ }
+ }
+ return (*search->callback)(cert, search->cbarg);
+}
+
+/* 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;
+ /* this is really traversal - the template is all certs */
+ CK_ATTRIBUTE cert_template[] = {
+ { CKA_CLASS, NULL, 0 }
+ };
+ CK_ULONG ctsize = sizeof(cert_template) / sizeof(cert_template[0]);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert);
+ nssList_SetCompareFunction(search->cached, compare_cert_by_issuer_sn);
+ 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 subj_tmpl[] =
+ {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 }
+ };
+ CK_ULONG stsize = (CK_ULONG)(sizeof(subj_tmpl) / sizeof(subj_tmpl[0]));
+ NSS_CK_SET_ATTRIBUTE_ITEM(subj_tmpl, 0, &g_ck_class_cert);
+ NSS_CK_SET_ATTRIBUTE_ITEM(subj_tmpl, 1, subject);
+ nssList_SetCompareFunction(search->cached, compare_cert_by_issuer_sn);
+ /* now traverse the token certs matching this template */
+ nssrv = traverse_objects_by_template(token, sessionOpt,
+ subj_tmpl, stsize,
+ retrieve_cert, search);
+ return nssrv;
+}
+
+NSS_IMPLEMENT PRStatus
+nssToken_TraverseCertificatesByNickname
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSUTF8 *name,
+ nssTokenCertSearch *search
+)
+{
+ PRStatus nssrv;
+ CK_ATTRIBUTE nick_tmpl[] =
+ {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_LABEL, NULL, 0 }
+ };
+ CK_ULONG ntsize = sizeof(nick_tmpl) / sizeof(nick_tmpl[0]);
+ /* set up the search template */
+ NSS_CK_SET_ATTRIBUTE_ITEM(nick_tmpl, 0, &g_ck_class_cert);
+ nick_tmpl[1].pValue = (CK_VOID_PTR)name;
+ nick_tmpl[1].ulValueLen = (CK_ULONG)nssUTF8_Length(name, &nssrv);
+ nssList_SetCompareFunction(search->cached, compare_cert_by_issuer_sn);
+ /* now traverse the token certs matching this template */
+ nssrv = traverse_objects_by_template(token, sessionOpt,
+ nick_tmpl, ntsize,
+ 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?
+ * 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.
+ */
+ nick_tmpl[1].ulValueLen++;
+ nssrv = traverse_objects_by_template(token, sessionOpt,
+ nick_tmpl, ntsize,
+ retrieve_cert, search);
+#endif
+ return nssrv;
+}
+
+NSS_IMPLEMENT PRStatus
+nssToken_TraverseCertificatesByEmail
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSASCII7 *email,
+ nssTokenCertSearch *search
+)
+{
+ PRStatus nssrv;
+ CK_ATTRIBUTE email_tmpl[] =
+ {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_NETSCAPE_EMAIL, NULL, 0 }
+ };
+ CK_ULONG etsize = sizeof(email_tmpl) / sizeof(email_tmpl[0]);
+ /* set up the search template */
+ NSS_CK_SET_ATTRIBUTE_ITEM(email_tmpl, 0, &g_ck_class_cert);
+ email_tmpl[1].pValue = (CK_VOID_PTR)email;
+ email_tmpl[1].ulValueLen = (CK_ULONG)nssUTF8_Length(email, &nssrv);
+ nssList_SetCompareFunction(search->cached, compare_cert_by_issuer_sn);
+ /* now traverse the token certs matching this template */
+ nssrv = traverse_objects_by_template(token, sessionOpt,
+ email_tmpl, 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[1].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
+)
+{
+ NSSCertificate *rvCert = NULL;
+ nssSession *session;
+ PRBool tokenObject;
+ PRStatus nssrv;
+ CK_ULONG ctsize;
+ CK_OBJECT_HANDLE object;
+ CK_ATTRIBUTE cert_template[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_ISSUER, NULL, 0 },
+ { CKA_SERIAL_NUMBER, NULL, 0 }
+ };
+ ctsize = sizeof(cert_template) / sizeof(cert_template[0]);
+ /* Set the unique id */
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 1, issuer);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 2, serial);
+ /* 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) {
+ NSSTrustDomain *td;
+ NSSCryptoContext *cc;
+ tokenObject = nssCKObject_IsAttributeTrue(object, CKA_TOKEN,
+ session, token->slot,
+ &nssrv);
+ if (tokenObject) {
+ td = token->trustDomain;
+ cc = NULL;
+ } else {
+ td = NULL;
+ cc = NULL; /* XXX how to recover the crypto context from
+ * the token?
+ */
+ }
+ add_object_instance(&rvCert->object, token, object, td, cc);
+ }
+ return rvCert;
+}
+
+NSS_IMPLEMENT NSSCertificate *
+nssToken_FindCertificateByEncodedCertificate
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSBER *encodedCertificate
+)
+{
+ NSSCertificate *rvCert = NULL;
+ nssSession *session;
+ PRBool tokenObject;
+ PRStatus nssrv;
+ CK_ULONG ctsize;
+ CK_OBJECT_HANDLE object;
+ CK_ATTRIBUTE cert_template[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_VALUE, NULL, 0 }
+ };
+ ctsize = sizeof(cert_template) / sizeof(cert_template[0]);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert);
+ NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 1, encodedCertificate);
+ /* 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) {
+ NSSTrustDomain *td;
+ NSSCryptoContext *cc;
+ tokenObject = nssCKObject_IsAttributeTrue(object, CKA_TOKEN,
+ session, token->slot,
+ &nssrv);
+ if (tokenObject) {
+ td = token->trustDomain;
+ cc = NULL;
+ } else {
+ td = NULL;
+ cc = NULL; /* XXX how to recover the crypto context from
+ * the token?
+ */
+ }
+ add_object_instance(&rvCert->object, token, object, td, cc);
+ }
+ return rvCert;
+}
+
+static void
+sha1_hash(NSSToken *token, NSSItem *input, NSSItem *output)
+{
+ NSSAlgorithmAndParameters *ap;
+ ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL);
+ (void)nssToken_Digest(token, NULL, ap, input, output, NULL);
+ nss_ZFreeIf(ap);
+}
+
+static void
+md5_hash(NSSToken *token, NSSItem *input, NSSItem *output)
+{
+ NSSAlgorithmAndParameters *ap;
+ ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL);
+ (void)nssToken_Digest(token, NULL, ap, input, output, NULL);
+ nss_ZFreeIf(ap);
+}
+
+NSS_IMPLEMENT PRStatus
+nssToken_ImportTrust
+(
+ NSSToken *tok,
+ nssSession *sessionOpt,
+ NSSTrust *trust,
+ NSSTrustDomain *trustDomain,
+ NSSCryptoContext *cryptoContext
+)
+{
+ PRStatus nssrv;
+ CK_OBJECT_HANDLE handle;
+ CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
+ CK_ATTRIBUTE trust_tmpl[] = {
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_CLASS, NULL, 0 },
+ { CKA_ISSUER, NULL, 0 },
+ { CKA_SERIAL_NUMBER, NULL, 0 },
+ { CKA_CERT_SHA1_HASH, NULL, 0 },
+ { CKA_CERT_MD5_HASH, NULL, 0 },
+ { CKA_TRUST_SERVER_AUTH, NULL, 0 },
+ { CKA_TRUST_CLIENT_AUTH, NULL, 0 },
+ { CKA_TRUST_EMAIL_PROTECTION, NULL, 0 },
+ { CKA_TRUST_CODE_SIGNING, NULL, 0 }
+ };
+ CK_ULONG tsize = sizeof(trust_tmpl) / sizeof(trust_tmpl[0]);
+ 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(tok, &c->encoding, &sha1_result);
+ md5_hash(tok, &c->encoding, &md5_result);
+ if (trustDomain) {
+ NSS_CK_SET_ATTRIBUTE_ITEM(trust_tmpl, 0, &g_ck_true);
+ } else {
+ NSS_CK_SET_ATTRIBUTE_ITEM(trust_tmpl, 0, &g_ck_false);
+ }
+ NSS_CK_SET_ATTRIBUTE_VAR( trust_tmpl, 1, tobjc);
+ NSS_CK_SET_ATTRIBUTE_ITEM(trust_tmpl, 2, &c->issuer);
+ NSS_CK_SET_ATTRIBUTE_ITEM(trust_tmpl, 3, &c->serial);
+ NSS_CK_SET_ATTRIBUTE_ITEM(trust_tmpl, 4, &sha1_result);
+ NSS_CK_SET_ATTRIBUTE_ITEM(trust_tmpl, 5, &md5_result);
+ /* now set the trust values */
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_tmpl, 6, trust->serverAuth);
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_tmpl, 7, trust->clientAuth);
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_tmpl, 8, trust->emailProtection);
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_tmpl, 9, trust->codeSigning);
+ /* import the trust object onto the token */
+ handle = import_object(tok, NULL, trust_tmpl, tsize);
+ if (handle != CK_INVALID_HANDLE) {
+ nssrv = add_object_instance(&trust->object, tok, handle,
+ trustDomain, cryptoContext);
+ } else {
+ nssrv = PR_FAILURE;
+ }
+ return nssrv;
+}
+
+static CK_OBJECT_HANDLE
+get_cert_trust_handle
+(
+ NSSToken *token,
+ nssSession *session,
+ NSSCertificate *c
+)
+{
+ CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
+ CK_ATTRIBUTE tobj_template[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_CERT_SHA1_HASH, NULL, 0 },
+ { CKA_ISSUER, NULL, 0 },
+ { CKA_SERIAL_NUMBER, NULL, 0 }
+ };
+ CK_ULONG tobj_size = sizeof(tobj_template) / sizeof(tobj_template[0]);
+ PRUint8 sha1[20]; /* this is cheating... */
+ NSSItem sha1_result;
+ sha1_result.data = sha1; sha1_result.size = sizeof sha1;
+ sha1_hash(token, &c->encoding, &sha1_result);
+ NSS_CK_SET_ATTRIBUTE_VAR( tobj_template, 0, tobjc);
+ NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 1, &sha1_result);
+ NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 2, &c->issuer);
+ NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 3, &c->serial);
+#ifdef NSS_3_4_CODE
+ if (PK11_HasRootCerts(token->pk11slot)) {
+ tobj_size -= 2;
+ }
+ /*
+ * 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
+ return find_object_by_template(token, session,
+ tobj_template, tobj_size);
+}
+
+NSS_IMPLEMENT NSSTrust *
+nssToken_FindTrustForCert
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSCertificate *c
+)
+{
+ PRStatus nssrv;
+ NSSTrust *rvTrust;
+ nssSession *session;
+ NSSArena *arena;
+ nssPKIObject *object;
+ CK_TRUST saTrust, caTrust, epTrust, csTrust;
+ CK_OBJECT_HANDLE tobjID;
+ CK_ATTRIBUTE trust_template[] = {
+ { CKA_TRUST_SERVER_AUTH, NULL, 0 },
+ { CKA_TRUST_CLIENT_AUTH, NULL, 0 },
+ { CKA_TRUST_EMAIL_PROTECTION, NULL, 0 },
+ { CKA_TRUST_CODE_SIGNING, NULL, 0 }
+ };
+ CK_ULONG trust_size = sizeof(trust_template) / sizeof(trust_template[0]);
+ session = (sessionOpt) ? sessionOpt : token->defaultSession;
+ tobjID = get_cert_trust_handle(token, session, c);
+ if (tobjID == CK_INVALID_HANDLE) {
+ return NULL;
+ }
+ /* Then use the trust object to find the trust settings */
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 0, saTrust);
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 1, caTrust);
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 2, epTrust);
+ NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 3, csTrust);
+ 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;
+ }
+ object = &rvTrust->object;
+ object->arena = arena;
+ object->refCount = 1;
+ object->instanceList = nssList_Create(arena, PR_TRUE);
+ if (!object->instanceList) {
+ nssArena_Destroy(arena);
+ return NULL;
+ }
+ object->instances = nssList_CreateIterator(object->instanceList);
+ if (!object->instances) {
+ nssArena_Destroy(arena);
+ return NULL;
+ }
+ /* need to figure out trust domain and/or crypto context */
+ nssrv = add_object_instance(object, token, tobjID,
+ token->trustDomain, NULL);
+ if (nssrv != PR_SUCCESS) {
+ nssArena_Destroy(arena);
+ return NULL;
+ }
+ rvTrust->serverAuth = saTrust;
+ rvTrust->clientAuth = caTrust;
+ rvTrust->emailProtection = epTrust;
+ rvTrust->codeSigning = csTrust;
+ return rvTrust;
+}
+
diff --git a/security/nss/lib/dev/devt.h b/security/nss/lib/dev/devt.h
index cf8a6309a..01de793a7 100644
--- a/security/nss/lib/dev/devt.h
+++ b/security/nss/lib/dev/devt.h
@@ -60,12 +60,18 @@ static const char DEVT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#include "nssckt.h"
#endif /* NSSCKT_H */
+#ifndef BASET_H
+#include "baset.h"
+#endif /* BASET_H */
+
#ifdef NSS_3_4_CODE
#include "secmodt.h"
#endif /* NSS_3_4_CODE */
PR_BEGIN_EXTERN_C
+typedef struct nssSessionStr nssSession;
+
/* The list of boolean flags used to describe properties of a
* module.
*/
@@ -138,6 +144,47 @@ struct nssSessionStr
PRBool isRW;
};
+typedef enum {
+ NSSCertificateType_Unknown = 0,
+ NSSCertificateType_PKIX = 1
+} NSSCertificateType;
+
+#ifdef nodef
+typedef enum {
+ nssTrustLevel_Unknown = 0,
+ nssTrustLevel_NotTrusted = 1,
+ nssTrustLevel_Trusted = 2,
+ nssTrustLevel_TrustedDelegator = 3,
+ nssTrustLevel_Valid = 4
+} nssTrustLevel;
+#else
+typedef CK_ULONG nssTrustLevel; /* for now */
+#endif
+
+typedef struct nssCryptokiInstanceStr nssCryptokiInstance;
+
+struct nssCryptokiInstanceStr
+{
+ CK_OBJECT_HANDLE handle;
+ NSSToken *token;
+};
+
+typedef struct nssTokenCertSearchStr nssTokenCertSearch;
+
+struct nssTokenCertSearchStr
+{
+ PRStatus (* callback)(NSSCertificate *c, void *arg);
+ void *cbarg;
+ nssList *cached;
+ NSSTrustDomain *trustDomain;
+ NSSCryptoContext *cryptoContext;
+};
+
+struct NSSAlgorithmAndParametersStr
+{
+ CK_MECHANISM mechanism;
+};
+
PR_END_EXTERN_C
#endif /* DEVT_H */
diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c
index cbe334f4b..b90dd4c6c 100644
--- a/security/nss/lib/dev/devtoken.c
+++ b/security/nss/lib/dev/devtoken.c
@@ -43,23 +43,10 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#include "devm.h"
#endif /* DEVM_H */
-/* for the cache... */
-#ifndef PKI_H
-#include "pki.h"
-#endif /* PKI_H */
-
#ifndef NSSCKEPV_H
#include "nssckepv.h"
#endif /* NSSCKEPV_H */
-#ifndef NSSPKI_H
-#include "nsspki.h"
-#endif /* NSSPKI_H */
-
-#ifndef PKI_H
-#include "pki.h"
-#endif /* PKI_H */
-
#ifndef CKHELPER_H
#include "ckhelper.h"
#endif /* CKHELPER_H */
@@ -207,330 +194,191 @@ nssToken_GetName
return tok->name;
}
-NSS_IMPLEMENT PRStatus
-nssToken_DeleteStoredObject
+NSS_IMPLEMENT NSSItem *
+nssToken_Digest
(
NSSToken *tok,
nssSession *sessionOpt,
- CK_OBJECT_HANDLE object
+ NSSAlgorithmAndParameters *ap,
+ NSSItem *data,
+ NSSItem *rvOpt,
+ NSSArena *arenaOpt
)
{
- nssSession *session = NULL;
CK_RV ckrv;
- PRStatus nssrv;
- PRBool createdSession;
- if (nssCKObject_IsAttributeTrue(object, CKA_TOKEN, tok->defaultSession,
- tok->slot, &nssrv)) {
- if (sessionOpt) {
- if (!nssSession_IsReadWrite(sessionOpt)) {
- return PR_FAILURE;;
- } else {
- session = sessionOpt;
- }
- } else if (nssSession_IsReadWrite(tok->defaultSession)) {
- session = tok->defaultSession;
- } else {
- session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE);
- createdSession = PR_TRUE;
- }
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+ NSSItem *rvItem = NULL;
+ nssSession *session;
+ session = (sessionOpt) ? sessionOpt : tok->defaultSession;
+ nssSession_EnterMonitor(session);
+ ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism);
+ if (ckrv != CKR_OK) {
+ nssSession_ExitMonitor(session);
+ return NULL;
}
-
- if (session == NULL) {
- return PR_FAILURE;
+#if 0
+ /* XXX the standard says this should work, but it doesn't */
+ ckrv = CKAPI(tok)->C_Digest(session->handle, NULL, 0, NULL, &digestLen);
+ if (ckrv != CKR_OK) {
+ nssSession_ExitMonitor(session);
+ return NULL;
}
-
- nssSession_EnterMonitor(session);
- ckrv = CKAPI(tok->slot)->C_DestroyObject(session->handle, object);
- nssSession_ExitMonitor(session);
- if (createdSession) {
- nssSession_Destroy(session);
+#endif
+ digestLen = 0; /* XXX for now */
+ digest = NULL;
+ if (rvOpt) {
+ if (rvOpt->size > 0 && rvOpt->size < digestLen) {
+ nssSession_ExitMonitor(session);
+ /* the error should be bad args */
+ return NULL;
+ }
+ if (rvOpt->data) {
+ digest = rvOpt->data;
+ }
+ digestLen = rvOpt->size;
+ }
+ if (!digest) {
+ digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
+ if (!digest) {
+ nssSession_ExitMonitor(session);
+ return NULL;
+ }
}
+ ckrv = CKAPI(tok)->C_Digest(session->handle,
+ (CK_BYTE_PTR)data->data,
+ (CK_ULONG)data->size,
+ (CK_BYTE_PTR)digest,
+ &digestLen);
+ nssSession_ExitMonitor(session);
if (ckrv != CKR_OK) {
- return PR_FAILURE;
+ nss_ZFreeIf(digest);
+ return NULL;
}
- return PR_SUCCESS;
+ if (!rvOpt) {
+ rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
+ }
+ return rvItem;
}
-NSS_IMPLEMENT CK_OBJECT_HANDLE
-nssToken_ImportObject
+NSS_IMPLEMENT PRStatus
+nssToken_BeginDigest
(
NSSToken *tok,
nssSession *sessionOpt,
- CK_ATTRIBUTE_PTR objectTemplate,
- CK_ULONG otsize
+ NSSAlgorithmAndParameters *ap
)
{
- 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;
- }
- }
- if (session == NULL) {
- return PR_FAILURE;
- }
+ nssSession *session;
+ session = (sessionOpt) ? sessionOpt : tok->defaultSession;
nssSession_EnterMonitor(session);
- ckrv = CKAPI(tok->slot)->C_CreateObject(session->handle,
- objectTemplate, otsize,
- &object);
+ ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism);
nssSession_ExitMonitor(session);
- if (createdSession) {
- nssSession_Destroy(session);
- }
- if (ckrv != CKR_OK) {
- return CK_INVALID_HANDLE;
- }
- return object;
+ return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}
-NSS_IMPLEMENT CK_OBJECT_HANDLE
-nssToken_FindObjectByTemplate
+NSS_IMPLEMENT PRStatus
+nssToken_ContinueDigest
(
NSSToken *tok,
nssSession *sessionOpt,
- CK_ATTRIBUTE_PTR cktemplate,
- CK_ULONG ctsize
+ NSSItem *item
)
{
- CK_SESSION_HANDLE hSession;
- CK_OBJECT_HANDLE rvObject;
- CK_ULONG count;
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);
+ ckrv = CKAPI(tok)->C_DigestUpdate(session->handle,
+ (CK_BYTE_PTR)item->data,
+ (CK_ULONG)item->size);
nssSession_ExitMonitor(session);
- if (ckrv != CKR_OK) {
- return CK_INVALID_HANDLE;
- }
- return rvObject;
-}
-
-extern const NSSError NSS_ERROR_MAXIMUM_FOUND;
-
-struct collect_arg_str
-{
- NSSArena *arena;
- nssList *list;
- PRUint32 maximum;
-};
-
-static PRStatus
-collect_certs_callback(NSSToken *t, nssSession *session,
- CK_OBJECT_HANDLE h, void *arg)
-{
- NSSCertificate *cert;
- struct collect_arg_str *ca = (struct collect_arg_str *)arg;
- cert = nssCertificate_CreateFromHandle(ca->arena, h, session, t->slot);
- if (!cert) {
- goto loser;
- }
- /* addref */
- nssList_Add(ca->list, (void *)cert);
- if (ca->maximum > 0 && nssList_Count(ca->list) >= ca->maximum) {
- /* signal the end of collection) */
- nss_SetError(NSS_ERROR_MAXIMUM_FOUND);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-loser:
- return PR_FAILURE;
+ return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}
-struct cert_callback_str {
- nssListIterator *cachedCerts;
- PRStatus (*callback)(NSSCertificate *c, void *arg);
- void *arg;
-};
-
-static PRStatus
-retrieve_cert(NSSToken *t, nssSession *session, CK_OBJECT_HANDLE h, void *arg)
-{
- NSSCertificate *cert = NULL;
- NSSCertificate *c;
- struct cert_callback_str *ccb = (struct cert_callback_str *)arg;
- if (ccb->cachedCerts) {
- for (c = (NSSCertificate *)nssListIterator_Start(ccb->cachedCerts);
- c != (NSSCertificate *)NULL;
- c = (NSSCertificate *)nssListIterator_Next(ccb->cachedCerts))
- {
- if (c->handle == h && c->token == t) {
- /* this is enough, right? */
- cert = c;
- break;
- }
- }
- nssListIterator_Finish(ccb->cachedCerts);
- }
- if (!cert) {
- /* Could not find cert, so create it */
- cert = nssCertificate_CreateFromHandle(NULL, h, session, t->slot);
- if (!cert) {
- goto loser;
- }
- }
- /* Got the cert, feed it to the callback */
- return (*ccb->callback)(cert, ccb->arg);
-loser:
- return PR_FAILURE;
-}
-
-#define OBJECT_STACK_SIZE 16
-
-static PRStatus
-nsstoken_TraverseObjects
+NSS_IMPLEMENT NSSItem *
+nssToken_FinishDigest
(
NSSToken *tok,
- nssSession *session,
- CK_ATTRIBUTE_PTR obj_template,
- CK_ULONG otsize,
- PRStatus (*callback)(NSSToken *t, nssSession *session,
- CK_OBJECT_HANDLE h, void *arg),
- void *arg
+ nssSession *sessionOpt,
+ NSSItem *rvOpt,
+ NSSArena *arenaOpt
)
{
- 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;
- nssList *objectList = NULL;
- slot = tok->slot;
- hSession = session->handle;
- objectStack = startOS;
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+ NSSItem *rvItem = NULL;
+ nssSession *session;
+ session = (sessionOpt) ? sessionOpt : tok->defaultSession;
nssSession_EnterMonitor(session);
- ckrv = CKAPI(slot)->C_FindObjectsInit(hSession, obj_template, otsize);
- if (ckrv != CKR_OK) {
+ ckrv = CKAPI(tok)->C_DigestFinal(session->handle, NULL, &digestLen);
+ if (ckrv != CKR_OK || digestLen == 0) {
nssSession_ExitMonitor(session);
- goto loser;
+ return NULL;
}
- while (PR_TRUE) {
- ckrv = CKAPI(slot)->C_FindObjects(hSession, objectStack,
- OBJECT_STACK_SIZE, &count);
- if (ckrv != CKR_OK) {
+ digest = NULL;
+ if (rvOpt) {
+ if (rvOpt->size > 0 && rvOpt->size < digestLen) {
nssSession_ExitMonitor(session);
- goto loser;
+ /* the error should be bad args */
+ return NULL;
}
- if (count == OBJECT_STACK_SIZE) {
- if (!objectList) {
- objectArena = NSSArena_Create();
- objectList = nssList_Create(objectArena, PR_FALSE);
- }
- objectStack = nss_ZNEWARRAY(objectArena, CK_OBJECT_HANDLE,
- OBJECT_STACK_SIZE);
- nssList_Add(objectList, objectStack);
- } else {
- break;
+ if (rvOpt->data) {
+ digest = rvOpt->data;
}
+ digestLen = rvOpt->size;
}
- ckrv = CKAPI(slot)->C_FindObjectsFinal(hSession);
+ if (!digest) {
+ digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
+ if (!digest) {
+ nssSession_ExitMonitor(session);
+ return NULL;
+ }
+ }
+ ckrv = CKAPI(tok)->C_DigestFinal(session->handle, digest, &digestLen);
nssSession_ExitMonitor(session);
if (ckrv != CKR_OK) {
- goto loser;
- }
- if (objectList) {
- nssListIterator *objects;
- objects = nssList_CreateIterator(objectList);
- for (objectStack = (CK_OBJECT_HANDLE *)nssListIterator_Start(objects);
- objectStack != NULL;
- objectStack = (CK_OBJECT_HANDLE *)nssListIterator_Next(objects)) {
- for (i=0; i<count; i++) {
- cbrv = (*callback)(tok, session, objectStack[i], arg);
- }
- }
- nssListIterator_Finish(objects);
- count = OBJECT_STACK_SIZE;
+ nss_ZFreeIf(digest);
+ return NULL;
}
- for (i=0; i<count; i++) {
- cbrv = (*callback)(tok, session, startOS[i], arg);
+ if (!rvOpt) {
+ rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
}
- if (objectArena)
- NSSArena_Destroy(objectArena);
- return PR_SUCCESS;
-loser:
- if (objectArena)
- NSSArena_Destroy(objectArena);
- return PR_FAILURE;
+ return rvItem;
}
-NSS_IMPLEMENT PRStatus
-nssToken_TraverseCertificates
+/* XXX of course this doesn't belong here */
+NSS_IMPLEMENT NSSAlgorithmAndParameters *
+NSSAlgorithmAndParameters_CreateSHA1Digest
(
- NSSToken *tok,
- nssSession *sessionOpt,
- PRStatus (*callback)(NSSCertificate *c, void *arg),
- void *arg
+ NSSArena *arenaOpt
)
{
- PRStatus nssrv;
- /* this is really traversal - the template is all certs */
- CK_ATTRIBUTE cert_template[] = {
- { CKA_CLASS, NULL, 0 }
- };
- CK_ULONG ctsize = sizeof(cert_template) / sizeof(cert_template[0]);
- NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert);
- nssrv = nssToken_TraverseCertificatesByTemplate(tok, sessionOpt, NULL,
- cert_template, ctsize,
- callback, arg);
- return nssrv;
+ 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 PRStatus
-nssToken_TraverseCertificatesByTemplate
+NSS_IMPLEMENT NSSAlgorithmAndParameters *
+NSSAlgorithmAndParameters_CreateMD5Digest
(
- NSSToken *tok,
- nssSession *sessionOpt,
- nssList *cachedList,
- CK_ATTRIBUTE_PTR cktemplate,
- CK_ULONG ctsize,
- PRStatus (*callback)(NSSCertificate *c, void *arg),
- void *arg
+ NSSArena *arenaOpt
)
{
- PRStatus rv;
- nssSession *session;
- struct cert_callback_str ccb;
- session = (sessionOpt) ? sessionOpt : tok->defaultSession;
- /* this isn't really traversal, it's find by template ... */
- if (cachedList) {
- ccb.cachedCerts = nssList_CreateIterator(cachedList);
- } else {
- ccb.cachedCerts = NULL;
- }
- ccb.callback = callback;
- ccb.arg = arg;
- rv = nsstoken_TraverseObjects(tok, session,
- cktemplate, ctsize,
- retrieve_cert, (void *)&ccb);
- return rv;
+ 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 279bfe0b2..fbd4ec37b 100644
--- a/security/nss/lib/dev/manifest.mn
+++ b/security/nss/lib/dev/manifest.mn
@@ -48,9 +48,10 @@ MODULE = security
CSRCS = \
devmod.c \
- devslot.c \
- devtoken.c \
- devutil.c \
+ devslot.c \
+ devobject.c \
+ devtoken.c \
+ devutil.c \
ckhelper.c \
$(NULL)
diff --git a/security/nss/lib/dev/nssdevt.h b/security/nss/lib/dev/nssdevt.h
index a402ddddd..a603ce545 100644
--- a/security/nss/lib/dev/nssdevt.h
+++ b/security/nss/lib/dev/nssdevt.h
@@ -64,8 +64,6 @@ typedef struct NSSSlotStr NSSSlot;
typedef struct NSSTokenStr NSSToken;
-typedef struct nssSessionStr nssSession;
-
PR_END_EXTERN_C
#endif /* NSSDEVT_H */
diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c
index 339cf7d2e..b70ebea86 100644
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -58,8 +58,9 @@
#include "pki3hack.h"
#include "dev3hack.h"
-/*#include "dev.h" */
+#include "dev.h"
#include "nsspki.h"
+#include "pkim.h"
#include "pkitm.h"
#define PK11_SEARCH_CHUNKSIZE 10
@@ -1135,6 +1136,23 @@ 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 = c;
+ return PR_SUCCESS;
+ }
+ dc = nssCertificate_GetDecoding(c);
+ founddc = nssCertificate_GetDecoding(*cfound);
+ if (!founddc->isNewerThan(founddc, dc)) {
+ *cfound = c;
+ }
+ return PR_SUCCESS;
+}
+
CERTCertificate *
PK11_FindCertFromNickname(char *nickname, void *wincx) {
@@ -1167,19 +1185,34 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) {
/* find token by name */
token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName);
if (token) {
+ nssTokenCertSearch search;
+ nssList *certList;
+ certList = nssList_Create(NULL, PR_FALSE);
+ (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD,
+ nickname,
+ certList);
+ /* set the search criteria */
+ search.callback = get_newest_cert;
+ search.cbarg = (void *)&cert;
+ search.cached = certList;
+ search.trustDomain = defaultTD;
+ search.cryptoContext = NULL;
/* find best cert on token */
- cert = nssTrustDomain_FindBestCertificateByNicknameForToken(
- defaultTD,
- token,
- (NSSUTF8 *)nickname,
- NULL,
- &usage,
- NULL);
+ nssToken_TraverseCertificatesByNickname(token, NULL,
+ (NSSUTF8 *)nickname,
+ &search);
+ nssList_Destroy(certList);
if (!cert) {
- /* don't have a "for token" here yet... */
- cert = NSSTrustDomain_FindCertificateByEmail(defaultTD,
- (NSSASCII7 *)nickname,
- NULL, &usage, NULL);
+ certList = nssList_Create(NULL, PR_FALSE);
+ (void)nssTrustDomain_GetCertsForEmailAddressFromCache(
+ defaultTD,
+ nickname,
+ certList);
+ search.cached = certList;
+ nssToken_TraverseCertificatesByNickname(token, NULL,
+ (NSSASCII7 *)nickname,
+ &search);
+ nssList_Destroy(certList);
}
}
} else {
@@ -1206,6 +1239,15 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) {
#endif
}
+static PRStatus
+collect_certs(NSSCertificate *c, void *arg)
+{
+ nssList *list = (nssList *)arg;
+ /* Add the cert to the return list */
+ nssList_AddUnique(list, (void *)c);
+ return PR_SUCCESS;
+}
+
CERTCertList *
PK11_FindCertsFromNickname(char *nickname, void *wincx) {
#ifdef NSS_CLASSIC
@@ -1233,11 +1275,13 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) {
PORT_Free(certID);
return certList;
#else
+ PRStatus nssrv;
char *delimit = NULL;
char *tokenName;
- CERTCertList *certList = CERT_NewCertList();
+ int i;
+ CERTCertList *certList = NULL;
NSSCertificate **foundCerts;
- NSSCertificate **pCerts;
+ NSSCertificate *c;
NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain();
if ((delimit = PORT_Strchr(nickname,':')) != NULL) {
NSSToken *token;
@@ -1247,14 +1291,25 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) {
/* find token by name */
token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName);
if (token) {
- /* find best cert on token */
- foundCerts = nssTrustDomain_FindCertificatesByNicknameForToken(
- defaultTD,
- token,
- (NSSUTF8 *)nickname,
- NULL,
- 0,
- NULL);
+ nssTokenCertSearch search;
+ PRUint32 count;
+ nssList *nameList;
+ nameList = nssList_Create(NULL, PR_FALSE);
+ (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD,
+ nickname,
+ nameList);
+ /* set the search criteria */
+ search.callback = collect_certs;
+ search.cbarg = nameList;
+ search.cached = nameList;
+ search.trustDomain = defaultTD;
+ search.cryptoContext = NULL;
+ nssrv = nssToken_TraverseCertificatesByNickname(token, NULL,
+ nickname, &search);
+ count = nssList_Count(nameList);
+ foundCerts = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1);
+ nssList_GetArray(nameList, (void **)foundCerts, count);
+ nssList_Destroy(nameList);
}
*delimit = ':';
} else {
@@ -1265,17 +1320,17 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) {
0,
NULL);
}
- pCerts = foundCerts;
- while (pCerts != NULL) {
- NSSCertificate *c = *pCerts;
- CERT_AddCertToListTail(certList, STAN_GetCERTCertificate(c));
- pCerts++;
- }
- if (CERT_LIST_HEAD(certList) == NULL) {
- CERT_DestroyCertList(certList);
- certList = NULL;
+ if (foundCerts) {
+ certList = CERT_NewCertList();
+ for (i=0, c = *foundCerts; c; c = foundCerts[++i]) {
+ CERT_AddCertToListTail(certList, STAN_GetCERTCertificate(c));
+ }
+ if (CERT_LIST_HEAD(certList) == NULL) {
+ CERT_DestroyCertList(certList);
+ certList = NULL;
+ }
+ nss_ZFreeIf(foundCerts);
}
- nss_ZFreeIf(foundCerts);
return certList;
#endif
}
@@ -1482,10 +1537,22 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert,
PORT_SetError( PK11_MapError(crv) );
}
+ if (!cert->nickname && nickname) {
+ cert->nickname = PORT_ArenaStrdup(cert->arena, nickname);
+ }
+
+ cert->pkcs11ID = certID;
+ cert->dbhandle = STAN_GetDefaultTrustDomain();
if (cert->slot == NULL) {
cert->slot = PK11_ReferenceSlot(slot);
if (cert->nssCertificate) {
- cert->nssCertificate->token = slot->nssToken;
+ nssPKIObjectInstance *instance;
+ NSSCertificate *c = cert->nssCertificate;
+ instance = nss_ZNEW(c->object.arena, nssPKIObjectInstance);
+ instance->cryptoki.token = slot->nssToken;
+ instance->cryptoki.handle = cert->pkcs11ID;
+ instance->trustDomain = cert->dbhandle;
+ nssList_Add(c->object.instanceList, instance);
} else {
cert->nssCertificate = STAN_GetNSSCertificate(cert);
}
@@ -2262,31 +2329,29 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot,
return PK11_TraverseSlot(slot, &callarg);
#else
- /* Alas, stan isn't really made for this... perhaps collect all matching
- * subject certs on the token and then pass the certs to the callback?
- */
struct nss3_cert_cbstr pk11cb;
PRStatus nssrv;
- NSSToken *tok;
- CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
- CK_ATTRIBUTE theTemplate[] = {
- { CKA_CLASS, NULL, 0 },
- { CKA_SUBJECT, NULL, 0 },
- };
- CK_ATTRIBUTE *attr = theTemplate;
- CK_ULONG templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]);
- PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++;
- PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len);
+ NSSToken *token;
+ NSSDER subject;
+ NSSTrustDomain *td;
+ nssList *subjectList;
+ nssTokenCertSearch search;
pk11cb.callback = callback;
pk11cb.arg = arg;
- tok = PK11Slot_GetNSSToken(slot);
- if (tok) {
- nssrv = nssToken_TraverseCertificatesByTemplate(tok, NULL, NULL,
- theTemplate, templateSize,
- convert_cert, &pk11cb);
- } else {
- return SECFailure;
- }
+ td = STAN_GetDefaultTrustDomain();
+ NSSITEM_FROM_SECITEM(&subject, &cert->derSubject);
+ subjectList = nssList_Create(NULL, PR_FALSE);
+ (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, subjectList);
+ /* set the search criteria */
+ search.callback = convert_cert;
+ search.cbarg = &pk11cb;
+ search.cached = subjectList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ token = PK11Slot_GetNSSToken(slot);
+ nssrv = nssToken_TraverseCertificatesBySubject(token, NULL,
+ &subject, &search);
+ nssList_Destroy(subjectList);
return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
#endif
}
@@ -2328,31 +2393,37 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot,
return PK11_TraverseSlot(slot, &callarg);
#else
- /* Alas, stan isn't really made for this... perhaps collect all matching
- * subject certs on the token and then pass the certs to the callback?
- */
struct nss3_cert_cbstr pk11cb;
PRStatus nssrv;
- NSSToken *tok;
- CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
- CK_ATTRIBUTE theTemplate[] = {
- { CKA_CLASS, NULL, 0 },
- { CKA_LABEL, NULL, 0 },
- };
- CK_ATTRIBUTE *attr = theTemplate;
- CK_ULONG templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]);
- PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++;
- PK11_SETATTRS(attr,CKA_LABEL,nickname->data,nickname->len);
+ NSSToken *token;
+ NSSTrustDomain *td;
+ NSSUTF8 *nick;
+ PRBool created = PR_FALSE;
+ nssTokenCertSearch search;
+ nssList *nameList;
pk11cb.callback = callback;
pk11cb.arg = arg;
- tok = PK11Slot_GetNSSToken(slot);
- if (tok) {
- nssrv = nssToken_TraverseCertificatesByTemplate(tok, NULL, NULL,
- theTemplate, templateSize,
- convert_cert, &pk11cb);
+ if (nickname->data[nickname->len-1] != '\0') {
+ nick = nssUTF8_Create(NULL, nssStringType_UTF8String,
+ nickname->data, nickname->len-1);
+ created = PR_TRUE;
} else {
- return SECFailure;
- }
+ nick = (NSSUTF8 *)nickname->data;
+ }
+ td = STAN_GetDefaultTrustDomain();
+ nameList = nssList_Create(NULL, PR_FALSE);
+ (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList);
+ /* set the search criteria */
+ search.callback = convert_cert;
+ search.cbarg = &pk11cb;
+ search.cached = nameList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ token = PK11Slot_GetNSSToken(slot);
+ nssrv = nssToken_TraverseCertificatesByNickname(token, NULL,
+ nick, &search);
+ nssList_Destroy(nameList);
+ if (created) nss_ZFreeIf(nick);
return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
#endif
}
@@ -2387,17 +2458,29 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot,
callarg.templateCount = templateSize;
return PK11_TraverseSlot(slot, &callarg);
#else
+ PRStatus nssrv;
+ NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
struct nss3_cert_cbstr pk11cb;
NSSToken *tok;
+ nssList *certList = nssList_Create(NULL, PR_FALSE);
+ nssTokenCertSearch search;
pk11cb.callback = callback;
pk11cb.arg = arg;
+ (void *)nssTrustDomain_GetCertsFromCache(td, certList);
+ /* set the search criteria */
+ search.callback = convert_cert;
+ search.cbarg = &pk11cb;
+ search.cached = certList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
tok = PK11Slot_GetNSSToken(slot);
if (tok) {
- return (SECStatus)nssToken_TraverseCertificates(tok, NULL,
- convert_cert, &pk11cb);
+ nssrv = nssToken_TraverseCertificates(tok, NULL, &search);
} else {
- return SECFailure;
+ nssrv = PR_FAILURE;
}
+ nssList_Destroy(certList);
+ return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
#endif
}
@@ -2441,12 +2524,11 @@ PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert,
CERTCertificate *rvCert = NULL;
NSSCertificate *c;
NSSDER derCert;
- derCert.data = (void *)cert->derCert.data;
- derCert.size = (PRUint32)cert->derCert.len;
+ NSSToken *tok;
+ tok = PK11Slot_GetNSSToken(slot);
+ NSSITEM_FROM_SECITEM(&derCert, &cert->derCert);
/* XXX login to slots */
- c = NSSTrustDomain_FindCertificateByEncodedCertificate(
- STAN_GetDefaultTrustDomain(),
- &derCert);
+ c = nssToken_FindCertificateByEncodedCertificate(tok, NULL, &derCert);
if (c) {
rvCert = STAN_GetCERTCertificate(c);
}
@@ -2803,7 +2885,11 @@ isOnList(CERTCertList *certList,CERTCertificate *cert)
return PR_FALSE;
}
static SECStatus
+#ifdef NSS_CLASSIC
pk11ListCertCallback(CERTCertificate *cert, SECItem *derCert, void *arg)
+#else
+pk11ListCertCallback(CERTCertificate *cert, void *arg)
+#endif
{
struct listCertsStr *listCertP = (struct listCertsStr *)arg;
CERTCertificate *newCert = NULL;
@@ -2821,11 +2907,15 @@ pk11ListCertCallback(CERTCertificate *cert, SECItem *derCert, void *arg)
if (!isUnique && cert->nickname) {
nickname = PORT_ArenaStrdup(listCertP->certList->arena,cert->nickname);
}
+#ifdef NSS_CLASSIC
if (derCert == NULL) {
newCert=CERT_DupCertificate(cert);
} else {
newCert=CERT_FindCertByDERCert(CERT_GetDefaultCertDB(),&cert->derCert);
}
+#else
+ newCert=CERT_DupCertificate(cert);
+#endif
if (newCert == NULL) return SECSuccess;
@@ -2870,13 +2960,6 @@ pk11ListCertCallback(CERTCertificate *cert, SECItem *derCert, void *arg)
return SECSuccess;
}
-static SECStatus
-pk11ListCertCallbackStub(CERTCertificate *cert, void *arg)
-{
- return pk11ListCertCallback(cert, NULL, arg);
-}
-
-
CERTCertList *
PK11_ListCerts(PK11CertListType type, void *pwarg)
@@ -2904,8 +2987,7 @@ PK11_ListCerts(PK11CertListType type, void *pwarg)
certList = CERT_NewCertList();
listCerts.type = type;
listCerts.certList = certList;
- /* XXX need to fix, this callback is of a different form */
- pk11cb.callback = pk11ListCertCallbackStub;
+ pk11cb.callback = pk11ListCertCallback;
pk11cb.arg = &listCerts;
NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb);
return certList;
diff --git a/security/nss/lib/pki/certificate.c b/security/nss/lib/pki/certificate.c
index 7554820e6..152931fc4 100644
--- a/security/nss/lib/pki/certificate.c
+++ b/security/nss/lib/pki/certificate.c
@@ -51,17 +51,9 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#include "dev.h"
#endif /* DEV_H */
-#ifndef CKHELPER_H
-#include "ckhelper.h"
-#endif /* CKHELPER_H */
-
-#ifndef CKT_H
#ifdef NSS_3_4_CODE
#include "pki3hack.h"
-#define NSSCKT_H
#endif
-#include "ckt.h"
-#endif /* CKT_H */
#ifndef BASE_H
#include "base.h"
@@ -69,37 +61,6 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
extern const NSSError NSS_ERROR_NOT_FOUND;
-/* Hm, sadly, I'm using PK11_HashBuf... Need to get crypto context going to
- * get rid of that
- */
-#ifndef NSS_3_4_CODE
-#define NSS_3_4_CODE
-#endif /* NSS_3_4_CODE */
-#include "pk11func.h"
-#include "hasht.h"
-
-/* I assume the following accessors into cert fields will be needed.
- * We need to be able to return basic cert info, however, these are
- * really PKCS#11 fields, so maybe not these in particular (mcgreer)
- */
-NSS_IMPLEMENT NSSUTF8 *
-NSSCertificate_GetLabel
-(
- NSSCertificate *c
-)
-{
- return c->nickname;
-}
-
-NSS_IMPLEMENT NSSItem *
-NSSCertificate_GetID
-(
- NSSCertificate *c
-)
-{
- return &c->id;
-}
-
NSS_IMPLEMENT NSSCertificate *
nssCertificate_AddRef
(
@@ -107,350 +68,29 @@ nssCertificate_AddRef
)
{
#ifdef NSS_3_4_CODE
+ /*
CERTCertificate *cc = STAN_GetCERTCertificate(c);
CERT_DupCertificate(cc);
+ */
#else
c->refCount++;
#endif
return c;
}
-/* NSS needs access to this function, but does anyone else? */
-/* XXX for the 3.4 hack anyway, yes */
-NSS_IMPLEMENT NSSCertificate *
-NSSCertificate_Create
-(
- NSSArena *arenaOpt
-)
-{
- NSSArena *arena;
- NSSCertificate *rvCert;
- arena = (arenaOpt) ? arenaOpt : nssArena_Create();
- if (!arena) {
- goto loser;
- }
- arena = NSSArena_Create();
- if(!arena) {
- return (NSSCertificate *)NULL;
- }
- rvCert = nss_ZNEW(arena, NSSCertificate);
- if (!rvCert) {
- goto loser;
- }
- rvCert->refCount = 1;
- if (!arenaOpt) {
- rvCert->arena = arena;
- }
- rvCert->handle = CK_INVALID_HANDLE;
- return rvCert;
-loser:
- if (!arenaOpt && arena) {
- nssArena_Destroy(arena);
- }
- return (NSSCertificate *)NULL;
-}
-
-static NSSCertificateType
-nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
-{
- CK_CERTIFICATE_TYPE ckCertType;
- ckCertType = *((CK_ULONG *)attrib->pValue);
- switch (ckCertType) {
- case CKC_X_509:
- return NSSCertificateType_PKIX;
- break;
- default:
- return NSSCertificateType_Unknown;
- }
-}
-
-static CK_OBJECT_HANDLE
-get_cert_trust_handle
-(
- NSSCertificate *c,
- nssSession *session
-)
-{
- CK_ULONG tobj_size;
- CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
- CK_ATTRIBUTE tobj_template[] = {
- { CKA_CLASS, NULL, 0 },
- { CKA_CERT_SHA1_HASH, NULL, 0 },
- { CKA_ISSUER, NULL, 0 },
- { CKA_SERIAL_NUMBER, NULL, 0 }
- };
- unsigned char sha1_hash[SHA1_LENGTH];
- tobj_size = sizeof(tobj_template) / sizeof(tobj_template[0]);
- NSS_CK_SET_ATTRIBUTE_VAR(tobj_template, 0, tobjc);
- /* First, use the SHA-1 hash of the cert to locate the trust object */
- /* XXX get rid of this PK11_ call! */
- PK11_HashBuf(SEC_OID_SHA1, sha1_hash, c->encoding.data, c->encoding.size);
- tobj_template[1].pValue = (CK_VOID_PTR)sha1_hash;
- tobj_template[1].ulValueLen = (CK_ULONG)SHA1_LENGTH;
- NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 2, &c->issuer);
- NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 3, &c->serial);
-#ifdef NSS_3_4_CODE
- if (PK11_HasRootCerts(c->token->pk11slot)) {
- tobj_size -= 2;
- }
-#endif
-
- /*
- * we need to arrange for the built-in token to loose the bottom 2
- * attributes so that old built-in tokens will continue to work.
- */
- return nssToken_FindObjectByTemplate(c->token, session,
- tobj_template, tobj_size);
-}
-
-static PRStatus
-nssCertificate_GetCertTrust
-(
- NSSCertificate *c,
- nssSession *session
-)
-{
- PRStatus nssrv;
- CK_TRUST saTrust, caTrust, epTrust, csTrust;
- CK_OBJECT_HANDLE tobjID;
- CK_ULONG trust_size;
- CK_ATTRIBUTE trust_template[] = {
- { CKA_TRUST_SERVER_AUTH, NULL, 0 },
- { CKA_TRUST_CLIENT_AUTH, NULL, 0 },
- { CKA_TRUST_EMAIL_PROTECTION, NULL, 0 },
- { CKA_TRUST_CODE_SIGNING, NULL, 0 }
- };
- trust_size = sizeof(trust_template) / sizeof(trust_template[0]);
- tobjID = get_cert_trust_handle(c, session);
- if (tobjID == CK_INVALID_HANDLE) {
- return PR_FAILURE;
- }
- /* Then use the trust object to find the trust settings */
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 0, saTrust);
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 1, caTrust);
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 2, epTrust);
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 3, csTrust);
- nssrv = nssCKObject_GetAttributes(tobjID,
- trust_template, trust_size,
- NULL, session, c->slot);
- c->trust.serverAuth = saTrust;
- c->trust.clientAuth = caTrust;
- c->trust.emailProtection = epTrust;
- c->trust.codeSigning = csTrust;
- return PR_SUCCESS;
-}
-
-#ifdef NSS_3_4_CODE
-static void make_nss3_nickname(NSSCertificate *c)
-{
- /* In NSS 3.4, the semantic is that nickname = token name + label */
- PRStatus utf8rv;
- NSSUTF8 *tokenName;
- NSSUTF8 *label;
- char *fullname;
- PRUint32 len, tlen;
- tokenName = nssToken_GetName(c->token);
- label = c->nickname ? c->nickname : c->email;
- if (!label) return;
- tlen = nssUTF8_Length(tokenName, &utf8rv); /* token name */
- tlen += 1; /* : */
- len = nssUTF8_Length(label, &utf8rv); /* label */
- len += 1; /* \0 */
- len += tlen;
- fullname = nss_ZAlloc(c->arena, len);
- utf8rv = nssUTF8_CopyIntoFixedBuffer(tokenName, fullname, tlen, ':');
- utf8rv = nssUTF8_CopyIntoFixedBuffer(label, fullname + tlen,
- len - tlen, '\0');
- nss_ZFreeIf(c->nickname);
- c->nickname = nssUTF8_Create(c->arena,
- nssStringType_UTF8String,
- fullname, len);
-}
-#endif
-
-/* Create a certificate from an object handle. */
-NSS_IMPLEMENT NSSCertificate *
-nssCertificate_CreateFromHandle
-(
- NSSArena *arenaOpt,
- CK_OBJECT_HANDLE object,
- nssSession *session,
- NSSSlot *slot
-)
-{
- NSSCertificate *rvCert;
- PRStatus nssrv;
- CK_ULONG template_size;
- CK_ATTRIBUTE cert_template[] = {
- { 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 },
- { CKA_NETSCAPE_EMAIL, NULL, 0 }
- };
- template_size = sizeof(cert_template) / sizeof(cert_template[0]);
- rvCert = NSSCertificate_Create(arenaOpt);
- if (!rvCert) {
- return (NSSCertificate *)NULL;
- }
- rvCert->handle = object;
- /* clean this up */
- rvCert->slot = slot;
- rvCert->token = slot->token;
- rvCert->trustDomain = slot->token->trustDomain;
- nssrv = nssCKObject_GetAttributes(object, cert_template, template_size,
- rvCert->arena, session, slot);
- if (nssrv) {
- /* okay, but if failed because one of the attributes could not be
- * found, do it gracefully (i.e., catch the error).
- */
- 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_UTF8(&cert_template[3], rvCert->nickname);
- NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[4], &rvCert->issuer);
- NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[5], &rvCert->subject);
- NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[6], &rvCert->serial);
- NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[7], rvCert->email);
- nssCertificate_GetCertTrust(rvCert, session);
-#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);
- email = dc->getEmailAddress(dc);
- if (email) rvCert->email = nssUTF8_Duplicate(email, rvCert->arena);
- }
- make_nss3_nickname(rvCert);
-#endif
- return rvCert;
-loser:
- NSSCertificate_Destroy(rvCert);
- return (NSSCertificate *)NULL;
-}
-
-static CK_OBJECT_HANDLE
-create_cert_trust_object
-(
- NSSCertificate *c,
- NSSTrust *trust
-)
-{
- CK_ULONG tobj_size;
- CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
- CK_ATTRIBUTE tobj_template[] = {
- { CKA_CLASS, NULL, 0 },
- { CKA_TOKEN, NULL, 0 },
- { CKA_ISSUER, NULL, 0 },
- { CKA_SERIAL_NUMBER, NULL, 0 },
- { CKA_CERT_SHA1_HASH, NULL, 0 },
- { CKA_CERT_MD5_HASH, NULL, 0 },
- { CKA_TRUST_SERVER_AUTH, NULL, 0 },
- { CKA_TRUST_CLIENT_AUTH, NULL, 0 },
- { CKA_TRUST_EMAIL_PROTECTION, NULL, 0 },
- { CKA_TRUST_CODE_SIGNING, NULL, 0 }
- };
- unsigned char sha1_hash[SHA1_LENGTH];
- unsigned char md5_hash[MD5_LENGTH];
- tobj_size = sizeof(tobj_template) / sizeof(tobj_template[0]);
- NSS_CK_SET_ATTRIBUTE_VAR( tobj_template, 0, tobjc);
- NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 1, &g_ck_true);
- NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 2, &c->issuer);
- NSS_CK_SET_ATTRIBUTE_ITEM(tobj_template, 3, &c->serial);
- /* First, use the SHA-1 hash of the cert to locate the trust object */
- /* XXX get rid of this PK11_ call! */
- PK11_HashBuf(SEC_OID_SHA1, sha1_hash, c->encoding.data, c->encoding.size);
- tobj_template[4].pValue = (CK_VOID_PTR)sha1_hash;
- tobj_template[4].ulValueLen = (CK_ULONG)SHA1_LENGTH;
- PK11_HashBuf(SEC_OID_MD5, md5_hash, c->encoding.data, c->encoding.size);
- tobj_template[5].pValue = (CK_VOID_PTR)md5_hash;
- tobj_template[5].ulValueLen = (CK_ULONG)MD5_LENGTH;
- /* now set the trust values */
- NSS_CK_SET_ATTRIBUTE_VAR(tobj_template, 6, trust->serverAuth);
- NSS_CK_SET_ATTRIBUTE_VAR(tobj_template, 7, trust->clientAuth);
- NSS_CK_SET_ATTRIBUTE_VAR(tobj_template, 8, trust->emailProtection);
- NSS_CK_SET_ATTRIBUTE_VAR(tobj_template, 9, trust->codeSigning);
- return nssToken_ImportObject(c->token, NULL, tobj_template, tobj_size);
-}
-
-NSS_IMPLEMENT PRStatus
-nssCertificate_SetCertTrust
-(
- NSSCertificate *c,
- NSSTrust *trust
-)
-{
- PRStatus nssrv;
- nssSession *session;
- PRBool createdSession;
- CK_OBJECT_HANDLE tobjID;
- CK_ULONG trust_size;
- CK_ATTRIBUTE trust_template[] = {
- { CKA_TRUST_SERVER_AUTH, NULL, 0 },
- { CKA_TRUST_CLIENT_AUTH, NULL, 0 },
- { CKA_TRUST_EMAIL_PROTECTION, NULL, 0 },
- { CKA_TRUST_CODE_SIGNING, NULL, 0 }
- };
- trust_size = sizeof(trust_template) / sizeof(trust_template[0]);
- if (!c->token) {
- /* must live on a token already */
- return PR_FAILURE;
- }
- session = c->token->defaultSession;
- tobjID = get_cert_trust_handle(c, session);
- if (tobjID == CK_INVALID_HANDLE) {
- /* trust object doesn't exist yet, create one */
- tobjID = create_cert_trust_object(c, trust);
- if (tobjID == CK_INVALID_HANDLE) {
- return PR_FAILURE;
- }
- c->trust.serverAuth = trust->serverAuth;
- c->trust.clientAuth = trust->clientAuth;
- c->trust.emailProtection = trust->emailProtection;
- c->trust.codeSigning = trust->codeSigning;
- return PR_SUCCESS;
- }
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 0, trust->serverAuth);
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 1, trust->clientAuth);
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 2, trust->emailProtection);
- NSS_CK_SET_ATTRIBUTE_VAR(trust_template, 3, trust->codeSigning);
- /* changing cert trust requires rw session XXX session objects */
- createdSession = PR_FALSE;
- if (!nssSession_IsReadWrite(session)) {
- createdSession = PR_TRUE;
- session = nssSlot_CreateSession(c->slot, NULL, PR_TRUE);
- }
- nssrv = nssCKObject_SetAttributes(tobjID,
- trust_template, trust_size,
- session, c->slot);
- if (createdSession) {
- nssSession_Destroy(session);
- }
- if (nssrv == PR_FAILURE) {
- return nssrv;
- }
- c->trust.serverAuth = trust->serverAuth;
- c->trust.clientAuth = trust->clientAuth;
- c->trust.emailProtection = trust->emailProtection;
- c->trust.codeSigning = trust->codeSigning;
- return PR_SUCCESS;
-}
-
NSS_IMPLEMENT PRStatus
NSSCertificate_Destroy
(
NSSCertificate *c
)
{
+#ifdef NSS_3_4_CODE
+ return NSSArena_Destroy(c->object.arena);
+#else
if (--c->refCount == 0) {
return NSSArena_Destroy(c->arena);
}
+#endif
return PR_SUCCESS;
}
@@ -461,13 +101,24 @@ NSSCertificate_DeleteStoredObject
NSSCallback *uhh
)
{
- /* delete it from storage, but leave it in memory */
- /* according to PKCS#11 2.11 section 13.2, the token must know how
- * to handle deletion when there are multiple threads attempting to use
- * the same object.
+ /* this needs more thought on what will happen when there are multiple
+ * instances
*/
/* XXX use callback to log in if neccessary */
- return nssToken_DeleteStoredObject(c->token, NULL, c->handle);
+ PRStatus nssrv = PR_SUCCESS;
+ nssPKIObjectInstance *instance;
+ nssListIterator *instances = c->object.instances;
+ for (instance = (nssPKIObjectInstance *)nssListIterator_Start(instances);
+ instance != (nssPKIObjectInstance *)NULL;
+ instance = (nssPKIObjectInstance *)nssListIterator_Next(instances))
+ {
+ nssrv = nssToken_DeleteStoredObject(&instance->cryptoki);
+ if (nssrv != PR_SUCCESS) {
+ break;
+ }
+ }
+ nssListIterator_Finish(instances);
+ return nssrv;
}
NSS_IMPLEMENT PRStatus
@@ -538,10 +189,6 @@ nssCertificate_GetDecoding
if (!c->decoding) {
c->decoding = nssDecodedCert_Create(NULL, &c->encoding, c->type);
}
-#ifdef NSS_3_4_CODE
- /* cause the trust bits to get updated in the encoded cert */
- (void) STAN_GetCERTCertificate(c);
-#endif
return c->decoding;
}
@@ -550,8 +197,10 @@ find_issuer_cert_for_identifier(NSSCertificate *c, NSSItem *id)
{
NSSCertificate *rvCert = NULL;
NSSCertificate **subjectCerts;
+ NSSTrustDomain *td;
+ td = NSSCertificate_GetTrustDomain(c);
/* Find all certs with this cert's issuer as the subject */
- subjectCerts = NSSTrustDomain_FindCertificatesBySubject(c->trustDomain,
+ subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td,
&c->issuer,
NULL,
0,
@@ -599,7 +248,17 @@ NSSCertificate_BuildChain
nssList *chain;
NSSItem *issuerID;
NSSCertificate **rvChain;
+ NSSTrustDomain *td;
nssDecodedCert *dc;
+ td = NSSCertificate_GetTrustDomain(c);
+#ifdef NSS_3_4_CODE
+ /* This goes down as a 3.4 hack. This function will need to be able to
+ * search both crypto contexts and trust domains for the chain.
+ */
+ if (!td) {
+ td = STAN_GetDefaultTrustDomain();
+ }
+#endif
chain = nssList_Create(NULL, PR_FALSE);
nssList_Add(chain, c);
if (statusOpt) *statusOpt = PR_SUCCESS;
@@ -620,7 +279,7 @@ NSSCertificate_BuildChain
PRBool tmpca = usage->nss3lookingForCA;
usage->nss3lookingForCA = PR_TRUE;
#endif
- c = NSSTrustDomain_FindBestCertificateBySubject(c->trustDomain,
+ c = NSSTrustDomain_FindBestCertificateBySubject(td,
&c->issuer,
timeOpt,
usage,
@@ -641,8 +300,8 @@ finish:
if (rvOpt) {
rvChain = rvOpt;
} else {
- rvChain = nss_ZNEWARRAY(arenaOpt,
- NSSCertificate *, nssList_Count(chain) + 1);
+ rvLimit = nssList_Count(chain);
+ rvChain = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvLimit + 1);
}
nssList_GetArray(chain, (void **)rvChain, rvLimit);
nssList_Destroy(chain);
@@ -656,12 +315,15 @@ NSSCertificate_GetTrustDomain
NSSCertificate *c
)
{
-#if 0
- if (c->trustDomain) {
- return nssTrustDomain_AddRef(c->trustDomain);
+ PRStatus nssrv = PR_SUCCESS;
+ nssPKIObjectInstance *instance;
+ nssList *instances = c->object.instanceList;
+ nssrv = nssList_GetArray(instances, (void **)&instance, 1);
+ if (nssrv == PR_SUCCESS) {
+ return instance->trustDomain;
+ } else {
+ return (NSSTrustDomain *)NULL;
}
-#endif
- return (NSSTrustDomain *)NULL;
}
NSS_IMPLEMENT NSSToken *
@@ -671,9 +333,6 @@ NSSCertificate_GetToken
PRStatus *statusOpt
)
{
- if (c->token) {
- return nssToken_AddRef(c->token);
- }
return (NSSToken *)NULL;
}
@@ -684,11 +343,6 @@ NSSCertificate_GetSlot
PRStatus *statusOpt
)
{
-#if 0
- if (c->token) {
- return nssToken_GetSlot(c->token);
- }
-#endif
return (NSSSlot *)NULL;
}
@@ -699,11 +353,6 @@ NSSCertificate_GetModule
PRStatus *statusOpt
)
{
-#if 0
- if (c->token) {
- return nssToken_GetModule(c->token);
- }
-#endif
return (NSSModule *)NULL;
}
@@ -799,15 +448,14 @@ NSSCertificate_GetPublicKey
NSSCertificate *c
)
{
+#if 0
CK_ATTRIBUTE pubktemplate[] = {
{ CKA_CLASS, NULL, 0 },
{ CKA_ID, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 }
};
-#if 0
PRStatus nssrv;
CK_ULONG count = sizeof(pubktemplate) / sizeof(pubktemplate[0]);
-#endif
NSS_CK_SET_ATTRIBUTE_ITEM(pubktemplate, 0, &g_ck_class_pubkey);
if (c->id.size > 0) {
/* CKA_ID */
@@ -824,7 +472,6 @@ NSSCertificate_GetPublicKey
return (NSSPublicKey *)NULL;
}
/* Try the cert's token first */
-#if 0
if (c->token) {
nssrv = nssToken_FindObjectByTemplate(c->token, pubktemplate, count);
}
diff --git a/security/nss/lib/pki/cryptocontext.c b/security/nss/lib/pki/cryptocontext.c
index 4b6322b37..9460ed1c1 100644
--- a/security/nss/lib/pki/cryptocontext.c
+++ b/security/nss/lib/pki/cryptocontext.c
@@ -39,6 +39,19 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#include "nsspki.h"
#endif /* NSSPKI_H */
+#ifndef PKIT_H
+#include "pkit.h"
+#endif /* PKIT_H */
+
+#ifndef DEV_H
+#include "dev.h"
+#endif /* DEV_H */
+
+#ifdef NSS_3_4_CODE
+#include "pk11func.h"
+#include "dev3hack.h"
+#endif
+
extern const NSSError NSS_ERROR_NOT_FOUND;
NSS_IMPLEMENT PRStatus
@@ -91,8 +104,28 @@ NSSCryptoContext_ImportCertificate
NSSCertificate *c
)
{
- nss_SetError(NSS_ERROR_NOT_FOUND);
- return PR_FAILURE;
+ NSSToken *token;
+ nssSession *session = NULL;
+#ifdef NSS_3_4_CODE
+ /* XXX hack alert - what this needs to do is find the preferred
+ * token for cert storage
+ */
+ if (PR_TRUE) {
+ PK11SlotInfo *slot = PK11_GetInternalSlot();
+ token = PK11Slot_GetNSSToken(slot);
+ }
+#endif
+ /*
+ * question - are there multiple available tokens for the crypto context?
+ * in that case, it needs to store a session for each one
+ */
+#ifdef nodef
+ session = get_token_session(cc, tok);
+ if (!session) {
+ return PR_FAILURE;
+ }
+#endif
+ return nssToken_ImportCertificate(token, session, c, NULL, cc);
}
NSS_IMPLEMENT NSSCertificate *
@@ -428,10 +461,10 @@ struct token_session_str {
nssSession *session;
};
+#ifdef nodef
static nssSession *
get_token_session(NSSCryptoContext *cc, NSSToken *tok)
{
-#if 0
struct token_session_str *ts;
for (ts = (struct token_session_str *)nssListIterator_Start(cc->sessions);
ts != (struct token_session_str *)NULL;
@@ -450,8 +483,8 @@ get_token_session(NSSCryptoContext *cc, NSSToken *tok)
nssList_AddElement(cc->sessionList, (void *)ts);
}
return ts->session;
-#endif
}
+#endif
NSS_IMPLEMENT NSSItem *
NSSCryptoContext_Decrypt
@@ -516,6 +549,7 @@ NSSCryptoContext_Decrypt
}
return rvData;
#endif
+ return NULL;
}
NSS_IMPLEMENT PRStatus
@@ -864,8 +898,8 @@ NSSCryptoContext_Digest
NSSArena *arenaOpt
)
{
- nss_SetError(NSS_ERROR_NOT_FOUND);
- return NULL;
+ return nssToken_Digest(cc->token, cc->session, apOpt,
+ data, rvOpt, arenaOpt);
}
NSS_IMPLEMENT PRStatus
@@ -876,8 +910,7 @@ NSSCryptoContext_BeginDigest
NSSCallback *uhhOpt
)
{
- nss_SetError(NSS_ERROR_NOT_FOUND);
- return PR_FAILURE;
+ return nssToken_BeginDigest(cc->token, cc->session, apOpt);
}
NSS_IMPLEMENT PRStatus
@@ -888,8 +921,12 @@ NSSCryptoContext_ContinueDigest
NSSItem *item
)
{
- nss_SetError(NSS_ERROR_NOT_FOUND);
- return PR_FAILURE;
+ /*
+ NSSAlgorithmAndParameters *ap;
+ ap = (apOpt) ? apOpt : cc->ap;
+ */
+ /* why apOpt? can't change it at this point... */
+ return nssToken_ContinueDigest(cc->token, cc->session, item);
}
NSS_IMPLEMENT NSSItem *
@@ -900,8 +937,7 @@ NSSCryptoContext_FinishDigest
NSSArena *arenaOpt
)
{
- nss_SetError(NSS_ERROR_NOT_FOUND);
- return NULL;
+ return nssToken_FinishDigest(cc->token, cc->session, rvOpt, arenaOpt);
}
NSS_IMPLEMENT NSSCryptoContext *
diff --git a/security/nss/lib/pki/pki.h b/security/nss/lib/pki/pki.h
index 0b83f0840..f9b02640e 100644
--- a/security/nss/lib/pki/pki.h
+++ b/security/nss/lib/pki/pki.h
@@ -54,27 +54,6 @@ nssCertificate_AddRef
NSSCertificate *c
);
-NSS_EXTERN NSSCertificate *
-nssCertificate_CreateFromHandle
-(
- NSSArena *arenaOpt,
- CK_OBJECT_HANDLE object,
- nssSession *session,
- NSSSlot *slot
-);
-
-NSS_EXTERN NSSUTF8 *
-NSSCertificate_GetLabel
-(
- NSSCertificate *c
-);
-
-NSS_EXTERN NSSItem *
-NSSCertificate_GetID
-(
- NSSCertificate *c
-);
-
PR_END_EXTERN_C
#endif /* PKI_H */
diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c
index 52170ce40..69d54e8ce 100644
--- a/security/nss/lib/pki/pki3hack.c
+++ b/security/nss/lib/pki/pki3hack.c
@@ -51,10 +51,6 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#include "dev.h"
#endif /* DEV_H */
-#ifndef CKHELPER_H
-#include "ckhelper.h"
-#endif /* CKHELPER_H */
-
#ifndef DEVNSS3HACK_H
#include "dev3hack.h"
#endif /* DEVNSS3HACK_H */
@@ -71,12 +67,20 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
NSSTrustDomain *g_default_trust_domain = NULL;
+NSSCryptoContext *g_default_crypto_context = NULL;
+
NSSTrustDomain *
STAN_GetDefaultTrustDomain()
{
return g_default_trust_domain;
}
+NSSCryptoContext *
+STAN_GetDefaultCryptoContext()
+{
+ return g_default_crypto_context;
+}
+
NSS_IMPLEMENT void
STAN_LoadDefaultNSS3TrustDomain
(
@@ -103,6 +107,7 @@ STAN_LoadDefaultNSS3TrustDomain
}
td->tokens = nssList_CreateIterator(td->tokenList);
g_default_trust_domain = td;
+ g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
}
NSS_IMPLEMENT PRStatus
@@ -136,7 +141,7 @@ STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
return NULL;
}
secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
- if (!secrv) {
+ if (secrv != SECSuccess) {
return NULL;
}
rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
@@ -299,6 +304,28 @@ nssDecodedPKIXCertificate_Create
return rvDC;
}
+static nssDecodedCert *
+create_decoded_pkix_cert_from_nss3cert
+(
+ NSSArena *arenaOpt,
+ CERTCertificate *cc
+)
+{
+ nssDecodedCert *rvDC;
+ rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
+ rvDC->type = NSSCertificateType_PKIX;
+ rvDC->data = (void *)cc;
+ rvDC->getIdentifier = nss3certificate_getIdentifier;
+ rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
+ rvDC->matchIdentifier = nss3certificate_matchIdentifier;
+ rvDC->getUsage = nss3certificate_getUsage;
+ rvDC->isValidAtTime = nss3certificate_isValidAtTime;
+ rvDC->isNewerThan = nss3certificate_isNewerThan;
+ rvDC->matchUsage = nss3certificate_matchUsage;
+ rvDC->getEmailAddress = nss3certificate_getEmailAddress;
+ return rvDC;
+}
+
NSS_IMPLEMENT PRStatus
nssDecodedPKIXCertificate_Destroy
(
@@ -336,10 +363,15 @@ get_nss3trust_from_cktrust(CK_TRUST t)
}
static CERTCertTrust *
-nssTrust_GetCERTCertTrust(NSSTrust *t, CERTCertificate *cc)
+nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, NSSToken *token,
+ CERTCertificate *cc)
{
CERTCertTrust *rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
unsigned int client;
+ NSSTrust *t = nssToken_FindTrustForCert(token, NULL, c);
+ if (!t) {
+ return NULL;
+ }
rvTrust->sslFlags = get_nss3trust_from_cktrust(t->serverAuth);
client = get_nss3trust_from_cktrust(t->clientAuth);
if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) {
@@ -357,26 +389,39 @@ nssTrust_GetCERTCertTrust(NSSTrust *t, CERTCertificate *cc)
return rvTrust;
}
+static nssPKIObjectInstance *
+get_cert_instance(NSSCertificate *c)
+{
+ nssPKIObjectInstance *instance;
+ instance = NULL;
+ nssList_GetArray(c->object.instanceList, (void **)&instance, 1);
+ return instance;
+}
+
static void
fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc)
{
+ nssPKIObjectInstance *instance = get_cert_instance(c);
/* fill other fields needed by NSS3 functions using CERTCertificate */
- /* handle */
- cc->pkcs11ID = c->handle;
- /* nickname */
- cc->nickname = PL_strdup(c->nickname);
- /* slot (ownSlot ?) (addref ?) */
- if (c->token) {
- cc->slot = c->token->pk11slot;
- }
- /* trust */
- cc->trust = nssTrust_GetCERTCertTrust(&c->trust, cc);
- cc->referenceCount++;
+ if (!cc->nickname && c->nickname) {
+ PRStatus nssrv;
+ int len = nssUTF8_Size(c->nickname, &nssrv);
+ cc->nickname = PORT_ArenaAlloc(cc->arena, len);
+ memcpy(cc->nickname, c->nickname, len-1);
+ cc->nickname[len-1] = '\0';
+ }
+ if (instance) {
+ nssCryptokiInstance *cryptoki = &instance->cryptoki;
+ /* slot (ownSlot ?) (addref ?) */
+ cc->slot = cryptoki->token->pk11slot;
+ /* pkcs11ID */
+ cc->pkcs11ID = cryptoki->handle;
+ /* trust */
+ cc->trust = nssTrust_GetCERTCertTrustForCert(c, cryptoki->token, cc);
+ /* database handle is now the trust domain */
+ cc->dbhandle = instance->trustDomain;
+ }
/* subjectList ? */
- /* pkcs11ID */
- cc->pkcs11ID = c->handle;
- /* database handle is now the trust domain */
- cc->dbhandle = c->trustDomain;
/* pointer back */
cc->nssCertificate = c;
}
@@ -396,6 +441,11 @@ STAN_GetCERTCertificate(NSSCertificate *c)
cc = (CERTCertificate *)dc->data;
if (!cc->nssCertificate) {
fill_CERTCertificateFields(c, cc);
+ } else if (!cc->trust) {
+ nssPKIObjectInstance *instance = get_cert_instance(c);
+ cc->trust = nssTrust_GetCERTCertTrustForCert(c,
+ instance->cryptoki.token,
+ cc);
}
return cc;
}
@@ -428,13 +478,13 @@ NSS_EXTERN NSSCertificate *
STAN_GetNSSCertificate(CERTCertificate *cc)
{
NSSCertificate *c;
+ nssPKIObject *object;
+ nssPKIObjectInstance *instance;
NSSArena *arena;
-
c = cc->nssCertificate;
if (c) {
return c;
}
-
/* i don't think this should happen. but if it can, need to create
* NSSCertificate from CERTCertificate values here. */
/* Yup, it can happen. */
@@ -442,24 +492,35 @@ STAN_GetNSSCertificate(CERTCertificate *cc)
if (!arena) {
return NULL;
}
- c = NSSCertificate_Create(arena);
+ c = nss_ZNEW(arena, NSSCertificate);
if (!c) {
goto loser;
}
+ object = &c->object;
NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
c->type = NSSCertificateType_PKIX;
- c->arena = arena;
+ object->arena = arena;
+ object->refCount = 1;
+ object->instanceList = nssList_Create(arena, PR_TRUE);
+ object->instances = nssList_CreateIterator(object->instanceList);
nssItem_Create(arena,
&c->issuer, cc->derIssuer.len, cc->derIssuer.data);
nssItem_Create(arena,
&c->subject, cc->derSubject.len, cc->derSubject.data);
- nssItem_Create(arena,
- &c->serial, cc->serialNumber.len, cc->serialNumber.data);
+ if (PR_TRUE) {
+ /* CERTCertificate stores serial numbers decoded. I need the DER
+ * here. sigh.
+ */
+ SECItem derSerial;
+ CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
+ nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
+ PORT_Free(derSerial.data);
+ }
if (cc->nickname) {
c->nickname = nssUTF8_Create(arena,
- nssStringType_UTF8String,
- (NSSUTF8 *)cc->nickname,
- PORT_Strlen(cc->nickname));
+ nssStringType_UTF8String,
+ (NSSUTF8 *)cc->nickname,
+ PORT_Strlen(cc->nickname));
}
if (cc->emailAddr) {
c->email = nssUTF8_Create(arena,
@@ -467,19 +528,15 @@ STAN_GetNSSCertificate(CERTCertificate *cc)
(NSSUTF8 *)cc->emailAddr,
PORT_Strlen(cc->emailAddr));
}
- c->trustDomain = (NSSTrustDomain *)cc->dbhandle;
+ instance = nss_ZNEW(arena, nssPKIObjectInstance);
+ instance->trustDomain = (NSSTrustDomain *)cc->dbhandle;
if (cc->slot) {
- c->token = PK11Slot_GetNSSToken(cc->slot);
- c->slot = c->token->slot;
+ instance->cryptoki.token = PK11Slot_GetNSSToken(cc->slot);
+ instance->cryptoki.handle = cc->pkcs11ID;
}
+ nssList_Add(object->instanceList, instance);
+ c->decoding = create_decoded_pkix_cert_from_nss3cert(arena, cc);
cc->nssCertificate = c;
- if (cc->trust) {
- CERTCertTrust *trust = cc->trust;
- c->trust.serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
- c->trust.clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
- c->trust.emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
- c->trust.codeSigning= get_stan_trust(trust->objectSigningFlags, PR_FALSE);
- }
return c;
loser:
nssArena_Destroy(arena);
@@ -487,47 +544,31 @@ loser:
}
NSS_EXTERN PRStatus
-STAN_ChangeCertTrust(NSSCertificate *c, CERTCertTrust *trust)
+STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
{
- CERTCertificate *cc = STAN_GetCERTCertificate(c);
+ PRStatus nssrv;
+ NSSCertificate *c = STAN_GetNSSCertificate(cc);
+ nssPKIObjectInstance *instance;
NSSTrust nssTrust;
/* Set the CERTCertificate's trust */
cc->trust = trust;
/* Set the NSSCerticate's trust */
+ nssTrust.certificate = c;
+ nssTrust.object.arena = nssArena_Create();
+ nssTrust.object.instanceList = nssList_Create(nssTrust.object.arena,
+ PR_FALSE);
+ nssTrust.object.instances = nssList_CreateIterator(
+ nssTrust.object.instanceList);
nssTrust.serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
nssTrust.clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
nssTrust.emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
- nssTrust.codeSigning= get_stan_trust(trust->objectSigningFlags, PR_FALSE);
- return nssCertificate_SetCertTrust(c, &nssTrust);
-}
-
-/* This is here to replace CERT_Traverse calls */
-static PRStatus
-traverse_certificates_by_template
-(
- NSSTrustDomain *td,
- nssList *cachedList,
- CK_ATTRIBUTE_PTR cktemplate,
- CK_ULONG ctsize,
- PRStatus (*callback)(NSSCertificate *c, void *arg),
- void *arg
-)
-{
- PRStatus nssrv;
- NSSToken *tok;
- for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
- tok != (NSSToken *)NULL;
- tok = (NSSToken *)nssListIterator_Next(td->tokens))
- {
- nssrv = nssToken_TraverseCertificatesByTemplate(tok, NULL, cachedList,
- cktemplate, ctsize,
- callback, arg);
- if (nssrv == PR_FAILURE) {
- return PR_FAILURE;
- }
- }
- nssListIterator_Finish(td->tokens);
- return PR_SUCCESS;
+ nssTrust.codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
+ instance = get_cert_instance(c);
+ /* maybe GetDefaultTrustToken()? */
+ nssrv = nssToken_ImportTrust(instance->cryptoki.token, NULL, &nssTrust,
+ instance->trustDomain, instance->cryptoContext);
+ nssArena_Destroy(nssTrust.object.arena);
+ return nssrv;
}
/* CERT_TraversePermCertsForSubject */
@@ -541,22 +582,20 @@ nssTrustDomain_TraverseCertificatesBySubject
)
{
PRStatus nssrv;
- nssList *subjectList;
- CK_ATTRIBUTE subj_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_SUBJECT, NULL, 0 }
- };
- CK_ULONG ctsize;
- ctsize = (CK_ULONG)(sizeof(subj_template) / sizeof(subj_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(subj_template, 0, &g_ck_class_cert);
- NSS_CK_SET_ATTRIBUTE_ITEM(subj_template, 1, subject);
- subjectList = nssList_Create(NULL, PR_FALSE);
- (void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList);
- nssrv = traverse_certificates_by_template(td, subjectList,
- subj_template, ctsize,
- callback, arg);
- nssList_Destroy(subjectList);
+ NSSArena *tmpArena;
+ NSSCertificate **subjectCerts;
+ NSSCertificate *c;
+ PRIntn i;
+ tmpArena = NSSArena_Create();
+ subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
+ 0, tmpArena);
+ if (subjectCerts) {
+ for (i=0, c = subjectCerts[i]; c; i++) {
+ nssrv = callback(c, arg);
+ if (nssrv != PR_SUCCESS) break;
+ }
+ }
+ nssArena_Destroy(tmpArena);
return nssrv;
}
@@ -571,23 +610,20 @@ nssTrustDomain_TraverseCertificatesByNickname
)
{
PRStatus nssrv;
- nssList *nickCerts;
- CK_ATTRIBUTE nick_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_LABEL, NULL, 0 }
- };
- CK_ULONG ctsize;
- ctsize = (CK_ULONG)(sizeof(nick_template) / sizeof(nick_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(nick_template, 0, &g_ck_class_cert);
- nick_template[1].pValue = (CK_VOID_PTR)nickname;
- nick_template[1].ulValueLen = (CK_ULONG)nssUTF8_Length(nickname, &nssrv);
- nickCerts = nssList_Create(NULL, PR_FALSE);
- (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nickname, nickCerts);
- nssrv = traverse_certificates_by_template(td, nickCerts,
- nick_template, ctsize,
- callback, arg);
- nssList_Destroy(nickCerts);
+ NSSArena *tmpArena;
+ NSSCertificate **nickCerts;
+ NSSCertificate *c;
+ PRIntn i;
+ tmpArena = NSSArena_Create();
+ nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
+ 0, tmpArena);
+ if (nickCerts) {
+ for (i=0, c = nickCerts[i]; c; i++) {
+ nssrv = callback(c, arg);
+ if (nssrv != PR_SUCCESS) break;
+ }
+ }
+ nssArena_Destroy(tmpArena);
return nssrv;
}
@@ -601,23 +637,33 @@ nssTrustDomain_TraverseCertificates
)
{
PRStatus nssrv;
+ NSSToken *token;
nssList *certList;
- CK_ATTRIBUTE cert_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- };
- CK_ULONG ctsize;
- ctsize = (CK_ULONG)(sizeof(cert_template) / sizeof(cert_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert);
+ 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);
- nssrv = traverse_certificates_by_template(td, certList,
- cert_template, ctsize,
- callback, arg);
+ /* set the search criteria */
+ search.callback = callback;
+ search.cbarg = arg;
+ search.cached = certList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ 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)
{
@@ -629,6 +675,7 @@ get_cert_type(NSSCertificateType nssType)
* type CK_CERTIFICATE_TYPE */
}
}
+#endif
NSS_IMPLEMENT NSSToken *
STAN_GetInternalToken(void)
@@ -643,6 +690,7 @@ nssTrustDomain_AddTempCertToPerm
NSSCertificate *c
)
{
+#if 0
NSSToken *token;
CK_CERTIFICATE_TYPE cert_type;
CK_ATTRIBUTE cert_template[] =
@@ -679,4 +727,6 @@ nssTrustDomain_AddTempCertToPerm
c->slot = token->slot;
/* Do the trust object */
return PR_SUCCESS;
+#endif
+ return PR_FAILURE;
}
diff --git a/security/nss/lib/pki/pki3hack.h b/security/nss/lib/pki/pki3hack.h
index c9c58e283..8acb34b4c 100644
--- a/security/nss/lib/pki/pki3hack.h
+++ b/security/nss/lib/pki/pki3hack.h
@@ -57,6 +57,9 @@ PR_BEGIN_EXTERN_C
NSS_EXTERN NSSTrustDomain *
STAN_GetDefaultTrustDomain();
+NSSCryptoContext *
+STAN_GetDefaultCryptoContext();
+
NSS_IMPLEMENT void
STAN_LoadDefaultNSS3TrustDomain
(
@@ -76,7 +79,7 @@ NSS_EXTERN NSSCertificate *
STAN_GetNSSCertificate(CERTCertificate *c);
NSS_EXTERN PRStatus
-STAN_ChangeCertTrust(NSSCertificate *c, CERTCertTrust *trust);
+STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust);
/* exposing this */
NSS_EXTERN NSSCertificate *
diff --git a/security/nss/lib/pki/pkim.h b/security/nss/lib/pki/pkim.h
index f16dafd67..192682720 100644
--- a/security/nss/lib/pki/pkim.h
+++ b/security/nss/lib/pki/pkim.h
@@ -129,13 +129,20 @@ nssTrustDomain_AddCertsToCache
PRUint32 numCerts
);
-NSS_EXTERN PRStatus
+NSS_EXTERN void
nssTrustDomain_RemoveCertFromCache
(
NSSTrustDomain *td,
NSSCertificate *cert
);
+NSS_EXTERN void
+nssTrustDomain_FlushCache
+(
+ NSSTrustDomain *td,
+ PRFloat64 threshold
+);
+
/*
* Remove all certs for the given token from the cache. This is
* needed if the token is removed.
diff --git a/security/nss/lib/pki/pkit.h b/security/nss/lib/pki/pkit.h
index a6dcfe662..22623f285 100644
--- a/security/nss/lib/pki/pkit.h
+++ b/security/nss/lib/pki/pkit.h
@@ -55,12 +55,6 @@ static const char PKIT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#ifdef NSS_3_4_CODE
#include "certt.h"
#include "pkcs11t.h"
-#define NSSCKT_H
-#include "ckt.h"
-#else
-#ifndef NSSCKT_H
-#include "nssckt.h"
-#endif /* NSSCKT_H */
#endif /* NSS_3_4_CODE */
#ifndef NSSPKIT_H
@@ -71,27 +65,46 @@ static const char PKIT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#include "nssdevt.h"
#endif /* NSSDEVT_H */
-PR_BEGIN_EXTERN_C
+#ifndef DEVT_H
+#include "devt.h"
+#endif /* DEVT_H */
-typedef enum {
- NSSCertificateType_Unknown = 0,
- NSSCertificateType_PKIX = 1
-} NSSCertificateType;
+PR_BEGIN_EXTERN_C
typedef struct nssDecodedCertStr nssDecodedCert;
-struct NSSTrustStr
+typedef struct nssPKIObjectInstanceStr nssPKIObjectInstance;
+
+typedef struct nssPKIObjectStr nssPKIObject;
+
+struct nssPKIObjectInstanceStr
{
- CK_TRUST serverAuth;
- CK_TRUST clientAuth;
- CK_TRUST emailProtection;
- CK_TRUST codeSigning;
+ nssCryptokiInstance cryptoki;
+ NSSTrustDomain *trustDomain;
+ NSSCryptoContext *cryptoContext;
};
-struct NSSCertificateStr
+struct nssPKIObjectStr
{
PRInt32 refCount;
NSSArena *arena;
+ nssList *instanceList; /* list of nssPKIObjectInstance */
+ nssListIterator *instances;
+};
+
+struct NSSTrustStr
+{
+ struct nssPKIObjectStr object;
+ NSSCertificate *certificate;
+ nssTrustLevel serverAuth;
+ nssTrustLevel clientAuth;
+ nssTrustLevel emailProtection;
+ nssTrustLevel codeSigning;
+};
+
+struct NSSCertificateStr
+{
+ struct nssPKIObjectStr object;
NSSCertificateType type;
NSSItem id;
NSSBER encoding;
@@ -100,12 +113,6 @@ struct NSSCertificateStr
NSSDER serial;
NSSUTF8 *nickname;
NSSASCII7 *email;
- NSSSlot *slot;
- NSSToken *token;
- NSSTrustDomain *trustDomain;
- NSSCryptoContext *cryptoContext;
- NSSTrust trust;
- CK_OBJECT_HANDLE handle;
nssDecodedCert *decoding;
};
@@ -134,6 +141,9 @@ struct NSSCryptoContextStr
{
PRInt32 refCount;
NSSArena *arena;
+ NSSTrustDomain *td;
+ NSSToken *token;
+ nssSession *session;
};
struct NSSTimeStr;
diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c
index 05bebd844..ce0afddcb 100644
--- a/security/nss/lib/pki/tdcache.c
+++ b/security/nss/lib/pki/tdcache.c
@@ -51,6 +51,39 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
#include "base.h"
#endif /* BASE_H */
+#ifdef DEBUG
+static PRLogModuleInfo *s_log = NULL;
+#endif
+
+#ifdef DEBUG
+static void log_item_dump(const char *msg, NSSItem *it)
+{
+ char buf[33];
+ int i, j;
+ for (i=0; i<10 && i<it->size; i++) {
+ sprintf(&buf[2*i], "%02X", ((PRUint8 *)it->data)[i]);
+ }
+ if (it->size>10) {
+ sprintf(&buf[2*i], "..");
+ i += 1;
+ for (j=it->size-1; i<=16 && j>10; i++, j--) {
+ sprintf(&buf[2*i], "%02X", ((PRUint8 *)it->data)[j]);
+ }
+ }
+ PR_LOG(s_log, PR_LOG_DEBUG, ("%s: %s", msg, buf));
+}
+#endif
+
+#ifdef DEBUG
+static void log_cert_ref(const char *msg, NSSCertificate *c)
+{
+ PR_LOG(s_log, PR_LOG_DEBUG, ("%s: %s", msg,
+ (c->nickname) ? c->nickname : c->email));
+ log_item_dump("\tserial", &c->serial);
+ log_item_dump("\tsubject", &c->subject);
+}
+#endif
+
/* Certificate cache routines */
/* XXX
@@ -59,36 +92,66 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
*/
/* should it live in its own arena? */
-struct nssTDCertificateCacheStr {
- PZLock *lock;
- nssHash *issuerAndSN;
- nssHash *subject;
- nssHash *nickname;
- nssHash *email;
+struct nssTDCertificateCacheStr
+{
+ PZLock *lock;
+ NSSArena *arena;
+ nssHash *issuerAndSN;
+ nssHash *subject;
+ nssHash *nickname;
+ nssHash *email;
};
-static NSSItem *
-get_issuer_and_serial_key(NSSArena *arena, NSSDER *issuer, NSSDER *serial)
-{
- NSSItem *rvKey;
- PRUint8 *buf;
- rvKey = nss_ZNEW(arena, NSSItem);
- rvKey->data = nss_ZAlloc(arena, issuer->size + serial->size);
- rvKey->size = issuer->size + serial->size;
- buf = (PRUint8 *)rvKey->data;
- nsslibc_memcpy(buf, issuer->data, issuer->size);
- nsslibc_memcpy(buf + issuer->size, serial->data, serial->size);
- return rvKey;
+struct cache_entry_str
+{
+ union {
+ NSSCertificate *cert;
+ nssList *list;
+ void *value;
+ } entry;
+ PRUint32 hits;
+ PRTime lastHit;
+};
+
+typedef struct cache_entry_str cache_entry;
+
+static cache_entry *
+new_cache_entry(NSSArena *arena, void *value)
+{
+ cache_entry *ce = nss_ZNEW(arena, cache_entry);
+ if (ce) {
+ ce->entry.value = value;
+ ce->hits = 1;
+ ce->lastHit = PR_Now();
+ }
+ return ce;
+}
+
+static PLHashNumber
+nss_certificate_hash
+(
+ const void *key
+)
+{
+ int i;
+ PLHashNumber h;
+ NSSCertificate *c = (NSSCertificate *)key;
+ h = 0;
+ for (i=0; i<c->issuer.size; i++)
+ h = (h >> 28) ^ (h << 4) ^ ((unsigned char *)c->issuer.data)[i];
+ for (i=0; i<c->serial.size; i++)
+ h = (h >> 28) ^ (h << 4) ^ ((unsigned char *)c->serial.data)[i];
+ return h;
}
-static PRBool cert_compare(void *v1, void *v2)
+static int
+nss_compare_certs(const void *v1, const void *v2)
{
- PRStatus rv;
+ PRStatus ignore;
NSSCertificate *c1 = (NSSCertificate *)v1;
NSSCertificate *c2 = (NSSCertificate *)v2;
- return
- (nssItem_Equal((NSSItem *)&c1->issuer, (NSSItem *)&c2->issuer, &rv) &&
- nssItem_Equal((NSSItem *)&c1->serial, (NSSItem *)&c2->serial, &rv));
+ return (int)(nssItem_Equal(&c1->issuer, &c2->issuer, &ignore) &&
+ nssItem_Equal(&c1->serial, &c2->serial, &ignore));
}
/* sort the subject list from newest to oldest */
@@ -115,38 +178,66 @@ nssTrustDomain_InitializeCache
PRUint32 cacheSize
)
{
- if (td->cache) {
+ NSSArena *arena;
+ nssTDCertificateCache *cache = td->cache;
+#ifdef DEBUG
+ s_log = PR_NewLogModule("nss_cache");
+ PR_ASSERT(s_log);
+#endif
+ PR_ASSERT(!cache);
+ arena = nssArena_Create();
+ if (!arena) {
return PR_FAILURE;
}
- td->cache = nss_ZNEW(td->arena, nssTDCertificateCache);
- td->cache->lock = PZ_NewLock(nssILockCache);
- if (!td->cache->lock) return PR_FAILURE;
- PZ_Lock(td->cache->lock);
+ cache = nss_ZNEW(arena, nssTDCertificateCache);
+ if (!cache) {
+ nssArena_Destroy(arena);
+ return PR_FAILURE;
+ }
+ cache->lock = PZ_NewLock(nssILockCache);
+ if (!cache->lock) {
+ nssArena_Destroy(arena);
+ return PR_FAILURE;
+ }
+ PZ_Lock(cache->lock);
/* Create the issuer and serial DER --> certificate hash */
- td->cache->issuerAndSN = nssHash_CreateItem(td->arena, cacheSize);
- if (!td->cache->issuerAndSN) goto loser;
+ cache->issuerAndSN = nssHash_Create(arena, cacheSize,
+ nss_certificate_hash,
+ nss_compare_certs,
+ PL_CompareValues);
+ if (!cache->issuerAndSN) {
+ goto loser;
+ }
/* Create the subject DER --> subject list hash */
- td->cache->subject = nssHash_CreateItem(td->arena, cacheSize);
- if (!td->cache->subject) goto loser;
+ cache->subject = nssHash_CreateItem(arena, cacheSize);
+ if (!cache->subject) {
+ goto loser;
+ }
/* Create the nickname --> subject list hash */
- td->cache->nickname = nssHash_CreateString(td->arena, cacheSize);
- if (!td->cache->nickname) goto loser;
+ cache->nickname = nssHash_CreateString(arena, cacheSize);
+ if (!cache->nickname) {
+ goto loser;
+ }
/* Create the email --> list of subject lists hash */
- td->cache->email = nssHash_CreateString(td->arena, cacheSize);
- if (!td->cache->email) goto loser;
- PZ_Unlock(td->cache->lock);
+ cache->email = nssHash_CreateString(arena, cacheSize);
+ if (!cache->email) {
+ goto loser;
+ }
+ cache->arena = arena;
+ PZ_Unlock(cache->lock);
+ td->cache = cache;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialized."));
+#endif
return PR_SUCCESS;
loser:
- if (td->cache->issuerAndSN)
- nssHash_Destroy(td->cache->issuerAndSN);
- if (td->cache->subject)
- nssHash_Destroy(td->cache->subject);
- if (td->cache->nickname)
- nssHash_Destroy(td->cache->nickname);
- PZ_Unlock(td->cache->lock);
- PZ_DestroyLock(td->cache->lock);
- nss_ZFreeIf(td->cache);
+ PZ_Unlock(cache->lock);
+ PZ_DestroyLock(cache->lock);
+ nssArena_Destroy(arena);
td->cache = NULL;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialization failed."));
+#endif
return PR_FAILURE;
}
@@ -156,142 +247,117 @@ nssTrustDomain_DestroyCache
NSSTrustDomain *td
)
{
- PZ_Lock(td->cache->lock);
- nssHash_Destroy(td->cache->issuerAndSN);
- nssHash_Destroy(td->cache->subject);
- nssHash_Destroy(td->cache->nickname);
- nssHash_Destroy(td->cache->email);
- PZ_Unlock(td->cache->lock);
PZ_DestroyLock(td->cache->lock);
- nss_ZFreeIf(td->cache);
+ nssArena_Destroy(td->cache->arena);
td->cache = NULL;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("Cache destroyed."));
+#endif
return PR_SUCCESS;
}
static PRStatus
-add_cert_to_cache(NSSTrustDomain *td, NSSCertificate *cert)
+remove_issuer_and_serial_entry
+(
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert
+)
+{
+ /* Remove the cert from the issuer/serial hash */
+ nssHash_Remove(cache->issuerAndSN, cert);
+#ifdef DEBUG
+ log_cert_ref("removed issuer/sn", cert);
+#endif
+ return PR_SUCCESS;
+}
+
+static PRStatus
+remove_subject_entry
+(
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert,
+ nssList **subjectList
+)
{
- nssArenaMark *mark;
- nssList *subjectList;
- nssList *subjects;
- NSSUTF8 *nickname = NULL;
- NSSUTF8 *email = NULL;
- NSSItem *ias = NULL;
PRStatus nssrv;
- ias = get_issuer_and_serial_key(td->arena, &cert->issuer, &cert->serial);
- PZ_Lock(td->cache->lock);
- /* If it exists in the issuer/serial hash, it's already in all */
- if (nssHash_Exists(td->cache->issuerAndSN, ias)) {
- PZ_Unlock(td->cache->lock);
- nss_ZFreeIf(ias);
- return PR_SUCCESS;
- }
- mark = nssArena_Mark(td->arena);
- if (!mark) {
- PZ_Unlock(td->cache->lock);
- nss_ZFreeIf(ias);
- return PR_FAILURE;
- }
- /* Add to issuer/serial hash */
- nssrv = nssHash_Add(td->cache->issuerAndSN, ias,
- nssCertificate_AddRef(cert));
- if (nssrv != PR_SUCCESS) goto loser;
- /* Add to subject hash */
- subjectList = (nssList *)nssHash_Lookup(td->cache->subject, &cert->subject);
- if (subjectList) {
- /* The subject is already in, add this cert to the list */
- nssrv = nssList_Add(subjectList,
- nssCertificate_AddRef(cert));
- if (nssrv != PR_SUCCESS) goto loser;
+ cache_entry *ce;
+ *subjectList = NULL;
+ /* Get the subject list for the cert's subject */
+ ce = (cache_entry *)nssHash_Lookup(cache->subject, &cert->subject);
+ if (ce) {
+ /* Remove the cert from the subject hash */
+ nssList_Remove(ce->entry.list, cert);
+ *subjectList = ce->entry.list;
+ nssrv = PR_SUCCESS;
+#ifdef DEBUG
+ log_cert_ref("removed cert", cert);
+ log_item_dump("from subject list", &cert->subject);
+#endif
} else {
- /* Create a new subject list for the subject */
- subjectList = nssList_Create(td->arena, PR_TRUE);
- nssList_SetSortFunction(subjectList, subject_list_sort);
- if (!subjectList) goto loser;
- /* To allow for different cert pointers, do list comparison by
- * actual cert values.
- */
- nssList_SetCompareFunction(subjectList, cert_compare);
- nssrv = nssList_Add(subjectList,
- nssCertificate_AddRef(cert));
- if (nssrv != PR_SUCCESS) goto loser;
- /* Add the subject list to the cache */
- nssrv = nssHash_Add(td->cache->subject, &cert->subject, subjectList);
- if (nssrv != PR_SUCCESS) goto loser;
- /* Since subject list was created, note the entry in the nickname
- * and email hashes.
- */
- /* nickname */
- if (cert->nickname) {
- nickname = nssUTF8_Duplicate(cert->nickname, td->arena);
- nssrv = nssHash_Add(td->cache->nickname, nickname, subjectList);
- if (nssrv != PR_SUCCESS) goto loser;
- }
- /* email */
- if (cert->email) {
- subjects = (nssList *)nssHash_Lookup(td->cache->email, cert->email);
- if (subjects) {
- /* The email address is already hashed, add this subject list */
- nssrv = nssList_Add(subjects, subjectList);
- if (nssrv != PR_SUCCESS) goto loser;
- } else {
- /* Create a new list of subject lists, add this subject */
- subjects = nssList_Create(td->arena, PR_TRUE);
- if (!subjects) goto loser;
- nssrv = nssList_Add(subjects, subjectList);
- if (nssrv != PR_SUCCESS) goto loser;
- /* Add the list of subject lists to the hash */
- email = nssUTF8_Duplicate(cert->email, td->arena);
- nssrv = nssHash_Add(td->cache->email, email, subjects);
- if (nssrv != PR_SUCCESS) goto loser;
- }
- }
+ nssrv = PR_FAILURE;
}
- nssrv = nssArena_Unmark(td->arena, mark);
- PZ_Unlock(td->cache->lock);
- return PR_SUCCESS;
-loser:
- nss_ZFreeIf(ias);
- nss_ZFreeIf(nickname);
- nss_ZFreeIf(email);
- nssArena_Release(td->arena, mark);
- PZ_Unlock(td->cache->lock);
- return PR_FAILURE;
+ return nssrv;
}
-NSS_IMPLEMENT PRStatus
-nssTrustDomain_AddCertsToCache
+static PRStatus
+remove_nickname_entry
(
- NSSTrustDomain *td,
- NSSCertificate **certs,
- PRUint32 numCerts
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert,
+ nssList *subjectList
)
{
- PRUint32 i;
- for (i=0; i<numCerts && certs[i]; i++) {
- if (add_cert_to_cache(td, certs[i]) != PR_SUCCESS) {
- return PR_FAILURE;
- }
+ PRStatus nssrv;
+ if (cert->nickname) {
+ nssHash_Remove(cache->nickname, cert->nickname);
+ nssrv = PR_SUCCESS;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("removed nickname %s", cert->nickname));
+#endif
+ } else {
+ nssrv = PR_FAILURE;
}
- return PR_SUCCESS;
+ return nssrv;
}
-static NSSItem *
-get_static_ias(NSSItem *s_ias, NSSDER *issuer, NSSDER *serial)
-{
- PRUint8 *buf;
- if (issuer->size + serial->size < s_ias->size) {
- buf = (PRUint8 *)s_ias->data;
- nsslibc_memcpy(buf, issuer->data, issuer->size);
- nsslibc_memcpy(buf + issuer->size, serial->data, serial->size);
- s_ias->size = issuer->size + serial->size;
- return s_ias;
- }
- s_ias->size = 0;
- return get_issuer_and_serial_key(NULL, issuer, serial);
+static PRStatus
+remove_email_entry
+(
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert,
+ nssList *subjectList
+)
+{
+ PRStatus nssrv = PR_FAILURE;
+ cache_entry *ce;
+ /* Find the subject list in the email hash */
+ if (cert->email) {
+ ce = (cache_entry *)nssHash_Lookup(cache->email, cert->email);
+ if (ce) {
+ nssList *subjects = ce->entry.list;
+ /* Remove the subject list from the email hash */
+ nssList_Remove(subjects, subjectList);
+#ifdef DEBUG
+ log_item_dump("removed subject list", &cert->subject);
+ PR_LOG(s_log, PR_LOG_DEBUG, ("for email %s", cert->email));
+#endif
+ if (nssList_Count(subjects) == 0) {
+ /* No more subject lists for email, delete list and
+ * remove hash entry
+ */
+ (void)nssList_Destroy(subjects);
+ nssHash_Remove(cache->email, cert->email);
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("removed email %s", cert->email));
+#endif
+ }
+ nssrv = PR_SUCCESS;
+ }
+ }
+ return nssrv;
}
-NSS_IMPLEMENT PRStatus
+NSS_IMPLEMENT void
nssTrustDomain_RemoveCertFromCache
(
NSSTrustDomain *td,
@@ -299,58 +365,61 @@ nssTrustDomain_RemoveCertFromCache
)
{
nssList *subjectList;
- nssList *subjects;
- NSSItem *ias;
- unsigned char buf[128];
- NSSItem s_ias;
- s_ias.data = (void *)buf;
- s_ias.size = sizeof(buf);
- ias = get_static_ias(&s_ias, &cert->issuer, &cert->serial);
- PZ_Lock(td->cache->lock);
- if (nssHash_Exists(td->cache->issuerAndSN, &ias)) {
- /* Whatchew talkin' bout, Willis? */
-#if 0
- nss_SetError(NSS_ERROR_CERTIFICATE_NOT_IN_CACHE);
+ PRStatus nssrv;
+#ifdef DEBUG
+ log_cert_ref("attempt to remove cert", cert);
#endif
- if (s_ias.size == 0) {
- nss_ZFreeIf(ias);
- }
+ PZ_Lock(td->cache->lock);
+ if (!nssHash_Exists(td->cache->issuerAndSN, cert)) {
PZ_Unlock(td->cache->lock);
- return PR_FAILURE;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("but it wasn't in the cache"));
+#endif
+ return;
}
- /* Remove the cert from the issuer/serial hash */
- nssHash_Remove(td->cache->issuerAndSN, ias);
- /* Get the subject list for the cert's subject */
- subjectList = (nssList *)nssHash_Lookup(td->cache->subject, &cert->subject);
- if (subjectList) {
- /* Remove the cert from the subject hash */
- nssList_Remove(subjectList, cert);
- if (nssList_Count(subjectList) == 0) {
- /* No more certs for subject ... */
- nssHash_Remove(td->cache->nickname, &cert->nickname);
- /* Find the subject list in the email hash */
- subjects = (nssList *)nssHash_Lookup(td->cache->email, cert->email);
- if (subjects) {
- /* Remove the subject list from the email hash */
- nssList_Remove(subjects, subjectList);
- if (nssList_Count(subjects) == 0) {
- /* No more subject lists for email, delete list and
- * remove hash entry
- */
- nssList_Destroy(subjects);
- nssHash_Remove(td->cache->email, cert->email);
- }
- }
- /* ... so destroy the subject list and remove the hash entry */
- nssList_Destroy(subjectList);
- nssHash_Remove(td->cache->subject, &cert->subject);
- }
+ nssrv = remove_issuer_and_serial_entry(td->cache, cert);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
}
- if (s_ias.size == 0) {
- nss_ZFreeIf(ias);
+ nssrv = remove_subject_entry(td->cache, cert, &subjectList);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ if (nssList_Count(subjectList) == 0) {
+ PRStatus nssrv2;
+ nssrv = remove_nickname_entry(td->cache, cert, 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 */
+ if (nssrv != PR_SUCCESS && nssrv2 != PR_SUCCESS) {
+ goto loser;
+ }
+#endif
+ (void)nssList_Destroy(subjectList);
+ nssHash_Remove(td->cache->subject, &cert->subject);
}
PZ_Unlock(td->cache->lock);
- return PR_SUCCESS;
+ return;
+loser:
+ /* if here, then the cache is inconsistent. For now, flush it. */
+ PZ_Unlock(td->cache->lock);
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("remove cert failed, flushing"));
+#endif
+ nssTrustDomain_FlushCache(td, -1.0);
+}
+
+/* This is used to remove all certs below a certain threshold, where
+ * the value is determined by how many times the cert has been requested
+ * and when the last request was.
+ */
+NSS_IMPLEMENT void
+nssTrustDomain_FlushCache
+(
+ NSSTrustDomain *td,
+ PRFloat64 threshold
+)
+{
}
struct token_cert_destructor {
@@ -361,6 +430,7 @@ struct token_cert_destructor {
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;
@@ -368,6 +438,7 @@ remove_token_certs(const void *k, void *v, void *a)
nssHash_Remove(tcd->cache->issuerAndSN, identifier);
/* remove from the other hashes */
}
+#endif
}
/*
@@ -390,6 +461,254 @@ nssTrustDomain_RemoveTokenCertsFromCache
return PR_SUCCESS;
}
+static PRStatus
+add_issuer_and_serial_entry
+(
+ NSSArena *arena,
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert
+)
+{
+ cache_entry *ce;
+ ce = new_cache_entry(arena, (void *)cert);
+#ifdef DEBUG
+ log_cert_ref("added to issuer/sn", cert);
+#endif
+ return nssHash_Add(cache->issuerAndSN, cert, (void *)ce);
+}
+
+static PRStatus
+add_subject_entry
+(
+ NSSArena *arena,
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert,
+ nssList **subjectList
+)
+{
+ PRStatus nssrv;
+ nssList *list;
+ cache_entry *ce;
+ *subjectList = NULL; /* this is only set if a new one is created */
+ ce = (cache_entry *)nssHash_Lookup(cache->subject, &cert->subject);
+ if (ce) {
+ ce->hits++;
+ ce->lastHit = PR_Now();
+ /* The subject is already in, add this cert to the list */
+ nssrv = nssList_AddUnique(ce->entry.list, cert);
+#ifdef DEBUG
+ log_cert_ref("added to existing subject list", cert);
+#endif
+ } else {
+ /* Create a new subject list for the subject */
+ list = nssList_Create(arena, PR_FALSE);
+ if (!list) {
+ return PR_FAILURE;
+ }
+ ce = new_cache_entry(arena, (void *)list);
+ if (!ce) {
+ return PR_FAILURE;
+ }
+ nssList_SetSortFunction(list, subject_list_sort);
+ /* Add the cert entry to this list of subjects */
+ nssrv = nssList_AddUnique(list, cert);
+ if (nssrv != PR_SUCCESS) {
+ return nssrv;
+ }
+ /* Add the subject list to the cache */
+ nssrv = nssHash_Add(cache->subject, &cert->subject, ce);
+ if (nssrv != PR_SUCCESS) {
+ return nssrv;
+ }
+ *subjectList = list;
+#ifdef DEBUG
+ log_cert_ref("created subject list", cert);
+#endif
+ }
+ return nssrv;
+}
+
+static PRStatus
+add_nickname_entry
+(
+ NSSArena *arena,
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert,
+ nssList *subjectList
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ cache_entry *ce;
+ ce = (cache_entry *)nssHash_Lookup(cache->nickname, cert->nickname);
+ if (ce) {
+ /* This is a collision. A nickname entry already exists for this
+ * subject, but a subject entry didn't. This would imply there are
+ * two subjects using the same nickname, which is not allowed.
+ */
+ return PR_FAILURE;
+ } else {
+ ce = new_cache_entry(arena, subjectList);
+ if (!ce) {
+ return PR_FAILURE;
+ }
+ nssrv = nssHash_Add(cache->nickname, cert->nickname, ce);
+#ifdef DEBUG
+ log_cert_ref("created nickname for", cert);
+#endif
+ }
+ return nssrv;
+}
+
+static PRStatus
+add_email_entry
+(
+ NSSArena *arena,
+ nssTDCertificateCache *cache,
+ NSSCertificate *cert,
+ nssList *subjectList
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ nssList *subjects;
+ cache_entry *ce;
+ ce = (cache_entry *)nssHash_Lookup(cache->email, cert->email);
+ if (ce) {
+ /* Already have an entry for this email address, but not subject */
+ subjects = ce->entry.list;
+ nssrv = nssList_AddUnique(subjects, subjectList);
+ ce->hits++;
+ ce->lastHit = PR_Now();
+#ifdef DEBUG
+ log_cert_ref("added subject to email for", cert);
+#endif
+ } else {
+ /* Create a new list of subject lists, add this subject */
+ subjects = nssList_Create(arena, PR_TRUE);
+ if (!subjects) {
+ return PR_FAILURE;
+ }
+ /* Add the new subject to the list */
+ nssrv = nssList_AddUnique(subjects, subjectList);
+ if (nssrv != PR_SUCCESS) {
+ return nssrv;
+ }
+ /* Add the new entry to the cache */
+ ce = new_cache_entry(arena, (void *)subjects);
+ if (!ce) {
+ return PR_FAILURE;
+ }
+ nssrv = nssHash_Add(cache->email, &cert->email, ce);
+ if (nssrv != PR_SUCCESS) {
+ return nssrv;
+ }
+#ifdef DEBUG
+ log_cert_ref("created email for", cert);
+#endif
+ }
+ return nssrv;
+}
+
+static PRStatus
+add_cert_to_cache
+(
+ NSSTrustDomain *td,
+ NSSCertificate *cert
+)
+{
+ NSSArena *arena;
+ nssList *subjectList;
+ PRStatus nssrv;
+ PRUint32 added = 0;
+ arena = td->cache->arena;
+ 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)) {
+#ifdef DEBUG
+ log_cert_ref("attempted to add cert already in cache", cert);
+#endif
+ PZ_Unlock(td->cache->lock);
+ return PR_SUCCESS;
+ }
+ /* create a new cache entry for this cert */
+ nssrv = add_issuer_and_serial_entry(arena, td->cache, cert);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ added++;
+ /* create a new subject list for this cert, or add to existing */
+ nssrv = add_subject_entry(arena, td->cache, cert, &subjectList);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ added++;
+ /* If a new subject entry was created, also need nickname and/or email */
+ if (subjectList != NULL) {
+ PRBool handle = PR_FALSE;
+ if (cert->nickname) {
+ nssrv = add_nickname_entry(arena, td->cache, cert, subjectList);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ handle = PR_TRUE;
+ added++;
+ }
+ if (cert->email) {
+ nssrv = add_email_entry(arena, td->cache, cert, subjectList);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ handle = PR_TRUE;
+ added += 2;
+ }
+#ifdef nodef
+ /* I think either a nickname or email address must be associated
+ * with the cert. However, certs are passed to NewTemp without
+ * either. This worked in the old code, so it must work now.
+ */
+ if (!handle) {
+ /* Require either nickname or email handle */
+ nssrv = PR_FAILURE;
+ goto loser;
+ }
+#endif
+ }
+ PZ_Unlock(td->cache->lock);
+ return nssrv;
+loser:
+ /* Remove any handles that have been created */
+ if (added >= 1) {
+ (void)remove_issuer_and_serial_entry(td->cache, cert);
+ }
+ if (added >= 2) {
+ (void)remove_subject_entry(td->cache, cert, &subjectList);
+ }
+ if (added == 3 || added == 5) {
+ (void)remove_nickname_entry(td->cache, cert, subjectList);
+ }
+ if (added >= 4) {
+ (void)remove_email_entry(td->cache, cert, subjectList);
+ }
+ PZ_Unlock(td->cache->lock);
+ return PR_FAILURE;
+}
+
+NSS_IMPLEMENT PRStatus
+nssTrustDomain_AddCertsToCache
+(
+ NSSTrustDomain *td,
+ NSSCertificate **certs,
+ PRUint32 numCerts
+)
+{
+ PRUint32 i;
+ for (i=0; i<numCerts && certs[i]; i++) {
+ if (add_cert_to_cache(td, certs[i]) != PR_SUCCESS) {
+ return PR_FAILURE;
+ }
+ }
+ return PR_SUCCESS;
+}
+
static NSSCertificate **
collect_subject_certs
(
@@ -411,8 +730,10 @@ collect_subject_certs
nssListIterator_Destroy(iter);
} else {
count = nssList_Count(subjectList);
- rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count);
- if (!rvArray) return (NSSCertificate **)NULL;
+ rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1);
+ if (!rvArray) {
+ return (NSSCertificate **)NULL;
+ }
nssList_GetArray(subjectList, (void **)rvArray, count);
}
return rvArray;
@@ -430,13 +751,22 @@ nssTrustDomain_GetCertsForSubjectFromCache
)
{
NSSCertificate **rvArray = NULL;
- nssList *subjectList;
+ cache_entry *ce;
+#ifdef DEBUG
+ log_item_dump("looking for cert by subject", subject);
+#endif
PZ_Lock(td->cache->lock);
- subjectList = (nssList *)nssHash_Lookup(td->cache->subject,
- (void *)subject);
+ ce = (cache_entry *)nssHash_Lookup(td->cache->subject, subject);
+ if (ce) {
+ ce->hits++;
+ ce->lastHit = PR_Now();
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
+#endif
+ }
PZ_Unlock(td->cache->lock);
- if (subjectList) {
- rvArray = collect_subject_certs(subjectList, certListOpt);
+ if (ce) {
+ rvArray = collect_subject_certs(ce->entry.list, certListOpt);
}
return rvArray;
}
@@ -453,13 +783,22 @@ nssTrustDomain_GetCertsForNicknameFromCache
)
{
NSSCertificate **rvArray = NULL;
- nssList *subjectList;
+ cache_entry *ce;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("looking for cert by nick %s", nickname));
+#endif
PZ_Lock(td->cache->lock);
- subjectList = (nssList *)nssHash_Lookup(td->cache->nickname,
- (void *)nickname);
+ ce = (cache_entry *)nssHash_Lookup(td->cache->nickname, nickname);
+ if (ce) {
+ ce->hits++;
+ ce->lastHit = PR_Now();
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
+#endif
+ }
PZ_Unlock(td->cache->lock);
- if (subjectList) {
- rvArray = collect_subject_certs(subjectList, certListOpt);
+ if (ce) {
+ rvArray = collect_subject_certs(ce->entry.list, certListOpt);
}
return rvArray;
}
@@ -476,13 +815,22 @@ nssTrustDomain_GetCertsForEmailAddressFromCache
)
{
NSSCertificate **rvArray = NULL;
- nssList *listOfSubjectLists;
+ cache_entry *ce;
nssList *collectList;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("looking for cert by email %s", email));
+#endif
PZ_Lock(td->cache->lock);
- listOfSubjectLists = (nssList *)nssHash_Lookup(td->cache->email,
- (void *)email);
+ ce = (cache_entry *)nssHash_Lookup(td->cache->email, email);
+ if (ce) {
+ ce->hits++;
+ ce->lastHit = PR_Now();
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
+#endif
+ }
PZ_Unlock(td->cache->lock);
- if (listOfSubjectLists) {
+ if (ce) {
nssListIterator *iter;
nssList *subjectList;
if (certListOpt) {
@@ -490,7 +838,7 @@ nssTrustDomain_GetCertsForEmailAddressFromCache
} else {
collectList = nssList_Create(NULL, PR_FALSE);
}
- iter = nssList_CreateIterator(listOfSubjectLists);
+ iter = nssList_CreateIterator(ce->entry.list);
for (subjectList = (nssList *)nssListIterator_Start(iter);
subjectList != (nssList *)NULL;
subjectList = (nssList *)nssListIterator_Next(iter)) {
@@ -510,10 +858,6 @@ nssTrustDomain_GetCertsForEmailAddressFromCache
return rvArray;
}
-#ifdef DEBUG
-static void debug_cache(NSSTrustDomain *td);
-#endif
-
/*
* Look for a specific cert in the cache
*/
@@ -525,27 +869,59 @@ nssTrustDomain_GetCertForIssuerAndSNFromCache
NSSDER *serial
)
{
- NSSCertificate *rvCert;
- NSSItem *ias;
- unsigned char buf[128];
- NSSItem s_ias;
- s_ias.data = (void *)buf;
- s_ias.size = sizeof(buf);
- ias = get_static_ias(&s_ias, issuer, serial);
+ NSSCertificate certkey;
+ NSSCertificate *rvCert = NULL;
+ cache_entry *ce;
+ certkey.issuer.data = issuer->data;
+ certkey.issuer.size = issuer->size;
+ certkey.serial.data = serial->data;
+ certkey.serial.size = serial->size;
#ifdef DEBUG
- debug_cache(td);
+ log_item_dump("looking for cert by issuer/sn, issuer", issuer);
+ log_item_dump(" serial", serial);
#endif
PZ_Lock(td->cache->lock);
- rvCert = (NSSCertificate *)nssHash_Lookup(td->cache->issuerAndSN, ias);
- PZ_Unlock(td->cache->lock);
- if (s_ias.size == 0) {
- nss_ZFreeIf(ias);
+ ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, &certkey);
+ if (ce) {
+ ce->hits++;
+ ce->lastHit = PR_Now();
+ rvCert = ce->entry.cert;
+#ifdef DEBUG
+ PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
+#endif
}
+ PZ_Unlock(td->cache->lock);
return rvCert;
}
-NSS_EXTERN NSSItem *
-STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der);
+#ifdef NSS_3_4_CODE
+static PRStatus
+issuer_and_serial_from_encoding
+(
+ NSSBER *encoding,
+ NSSDER *issuer,
+ NSSDER *serial
+)
+{
+ SECItem derCert, derIssuer, derSerial;
+ SECStatus secrv;
+ derCert.data = (unsigned char *)encoding->data;
+ derCert.len = encoding->size;
+ secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
+ if (secrv != SECSuccess) {
+ return PR_FAILURE;
+ }
+ secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
+ if (secrv != SECSuccess) {
+ return PR_FAILURE;
+ }
+ issuer->data = derIssuer.data;
+ issuer->size = derIssuer.len;
+ serial->data = derSerial.data;
+ serial->size = derSerial.len;
+ return PR_SUCCESS;
+}
+#endif
/*
* Look for a specific cert in the cache
@@ -557,16 +933,24 @@ nssTrustDomain_GetCertByDERFromCache
NSSDER *der
)
{
- NSSItem *identifier = NULL;
- NSSCertificate *rvCert = NULL;
+ PRStatus nssrv = PR_FAILURE;
+ NSSDER issuer, serial;
+ NSSCertificate *rvCert;
#ifdef NSS_3_4_CODE
- identifier = STAN_GetCertIdentifierFromDER(NULL, der);
+ nssrv = issuer_and_serial_from_encoding(der, &issuer, &serial);
#endif
- if (identifier) {
- rvCert = (NSSCertificate *)nssHash_Lookup(td->cache->issuerAndSN,
- identifier);
+ if (nssrv != PR_SUCCESS) {
+ return NULL;
}
- nss_ZFreeIf(identifier);
+#ifdef DEBUG
+ log_item_dump("looking for cert by DER", der);
+#endif
+ rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td,
+ &issuer, &serial);
+#ifdef NSS_3_4_CODE
+ PORT_Free(issuer.data);
+ PORT_Free(serial.data);
+#endif
return rvCert;
}
@@ -603,92 +987,3 @@ nssTrustDomain_GetCertsFromCache
return rvArray;
}
-#ifdef DEBUG
-static int el_count = 0;
-
-static void ias_iter(const void *k, void *v, void *a)
-{
- PRUint32 i;
- NSSItem *ias = (NSSItem *)k;
- fprintf(stderr, "[%3d]\n", el_count);
- fprintf(stderr, "ISSUER AND SERIAL: ");
- for (i=0; i<ias->size; i++) {
- fprintf(stderr, "%02x", ((unsigned char *)ias->data)[i]);
- }
- fprintf(stderr, "\n");
- fprintf(stderr, "CERT: %p\n", v);
- fprintf(stderr, "\n\n");
- el_count++;
-}
-
-static void print_sub_list(nssList *l)
-{
- NSSCertificate *c;
- nssListIterator *iter = nssList_CreateIterator(l);
- for (c = (NSSCertificate *)nssListIterator_Start(iter);
- c != NULL;
- c = (NSSCertificate *)nssListIterator_Next(iter)) {
- fprintf(stderr, "CERT: %p\n", c);
- }
- nssListIterator_Finish(iter);
- nssListIterator_Destroy(iter);
-}
-
-static void sub_iter(const void *k, void *v, void *a)
-{
- PRUint32 i;
- NSSDER *sub = (NSSDER *)k;
- fprintf(stderr, "[%3d]\n", el_count);
- fprintf(stderr, "SUBJECT: ");
- for (i=0; i<sub->size; i++) {
- fprintf(stderr, "%02x", ((unsigned char *)sub->data)[i]);
- }
- fprintf(stderr, "\n");
- print_sub_list((nssList *)v);
- fprintf(stderr, "\n\n");
-}
-
-static void nik_iter(const void *k, void *v, void *a)
-{
- NSSUTF8 *nick = (NSSUTF8 *)k;
- fprintf(stderr, "[%3d]\n", el_count);
- fprintf(stderr, "NICKNAME: %s\n", (char *)nick);
- fprintf(stderr, "SUBJECT_LIST: %p\n", v);
- fprintf(stderr, "\n");
-}
-
-static void print_eml_list(nssList *l)
-{
- nssList *s;
- nssListIterator *iter = nssList_CreateIterator(l);
- for (s = (nssList *)nssListIterator_Start(iter);
- s != NULL;
- s = (nssList *)nssListIterator_Next(iter)) {
- fprintf(stderr, "LIST: %p\n", s);
- }
- nssListIterator_Finish(iter);
- nssListIterator_Destroy(iter);
-}
-
-static void eml_iter(const void *k, void *v, void *a)
-{
- NSSASCII7 *email = (NSSASCII7 *)k;
- fprintf(stderr, "[%3d]\n", el_count);
- fprintf(stderr, "EMAIL: %s\n", (char *)email);
- print_eml_list((nssList *)v);
- fprintf(stderr, "\n");
-}
-
-static void debug_cache(NSSTrustDomain *td)
-{
- el_count = 0;
- nssHash_Iterate(td->cache->issuerAndSN, ias_iter, NULL);
- el_count = 0;
- nssHash_Iterate(td->cache->subject, sub_iter, NULL);
- el_count = 0;
- nssHash_Iterate(td->cache->nickname, nik_iter, NULL);
- el_count = 0;
- nssHash_Iterate(td->cache->email, eml_iter, NULL);
-}
-#endif
-
diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c
index de3de850c..0cbf021a9 100644
--- a/security/nss/lib/pki/trustdomain.c
+++ b/security/nss/lib/pki/trustdomain.c
@@ -114,7 +114,8 @@ NSSTrustDomain_Destroy
if (--td->refCount == 0) {
/* Destroy each token in the list of tokens */
if (td->tokens) {
- nssList_DestroyElements(td->tokenList, token_destructor);
+ nssList_Clear(td->tokenList, token_destructor);
+ nssList_Destroy(td->tokenList);
}
/* Destroy the trust domain */
nssArena_Destroy(td->arena);
@@ -354,12 +355,10 @@ NSSTrustDomain_ImportEncodedPublicKey
}
struct get_best_cert_arg_str {
- NSSTrustDomain *td;
NSSCertificate *cert;
NSSTime *time;
NSSUsage *usage;
NSSPolicies *policies;
- nssList *cached;
};
static PRStatus
@@ -400,59 +399,9 @@ get_best_cert(NSSCertificate *c, void *arg)
return PR_SUCCESS;
}
-static NSSCertificate *
-find_best_cert_for_template
-(
- NSSTrustDomain *td,
- NSSToken *token,
- struct get_best_cert_arg_str *best,
- CK_ATTRIBUTE_PTR cktemplate,
- CK_ULONG ctsize
-)
-{
- PRStatus nssrv;
- NSSToken *tok;
- if (token) {
- nssrv = nssToken_TraverseCertificatesByTemplate(token, NULL,
- best->cached,
- cktemplate, ctsize,
- get_best_cert, best);
- } else {
- /* we need to lock the iterator */
- for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
- tok != (NSSToken *)NULL;
- tok = (NSSToken *)nssListIterator_Next(td->tokens))
- {
- nssrv = nssToken_TraverseCertificatesByTemplate(tok, NULL,
- best->cached,
- cktemplate, ctsize,
- get_best_cert,
- best);
- }
- nssListIterator_Finish(td->tokens);
- }
- /* Cache the cert before returning */
- /*nssTrustDomain_AddCertsToCache(td, &best->cert, 1);*/
- /* rjr handle orphanned certs in cache for now. real fix will be Ian's
- * crypto object */
- if (best->cert == NULL) {
- if (nssList_Count(best->cached) >= 1) {
- NSSCertificate * candidate;
-
- nssList_GetArray(best->cached,&candidate,1);
- if (candidate) {
- best->cert = nssCertificate_AddRef(candidate);
- }
- }
- }
- return best->cert;
-}
-
struct collect_arg_str {
nssList *list;
PRUint32 maximum;
- NSSArena *arena;
- NSSCertificate **rvOpt;
};
extern const NSSError NSS_ERROR_MAXIMUM_FOUND;
@@ -471,105 +420,6 @@ collect_certs(NSSCertificate *c, void *arg)
return PR_SUCCESS;
}
-static NSSCertificate **
-find_all_certs_for_template
-(
- NSSTrustDomain *td,
- NSSToken *token,
- struct collect_arg_str *ca,
- CK_ATTRIBUTE_PTR cktemplate,
- CK_ULONG ctsize
-)
-{
- NSSCertificate **certs = NULL;
- PRStatus nssrv;
- PRUint32 count;
- NSSToken *tok;
- if (token) {
- nssrv = nssToken_TraverseCertificatesByTemplate(token, NULL, ca->list,
- cktemplate, ctsize,
- collect_certs, ca);
- } else {
- /* we need to lock the iterator */
- for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
- tok != (NSSToken *)NULL;
- tok = (NSSToken *)nssListIterator_Next(td->tokens))
- {
- nssrv = nssToken_TraverseCertificatesByTemplate(tok, NULL,
- ca->list,
- cktemplate, ctsize,
- collect_certs, ca);
- }
- nssListIterator_Finish(td->tokens);
- }
- count = nssList_Count(ca->list);
- if (ca->rvOpt) {
- certs = ca->rvOpt;
- } else {
- certs = nss_ZNEWARRAY(ca->arena, NSSCertificate *, count + 1);
- }
- nssrv = nssList_GetArray(ca->list, (void **)certs, count);
- /* Cache the certs before returning */
- /*nssTrustDomain_AddCertsToCache(td, certs, count);*/
- return certs;
-}
-
-/* XXX
- * This is really a hack for PK11_ calls that want to specify the token to
- * do lookups on (see PK11_FindCertFromNickname). I don't think this
- * is something we want to keep.
- */
-NSS_IMPLEMENT NSSCertificate *
-nssTrustDomain_FindBestCertificateByNicknameForToken
-(
- NSSTrustDomain *td,
- NSSToken *token,
- NSSUTF8 *name,
- NSSTime *timeOpt, /* NULL for "now" */
- NSSUsage *usage,
- NSSPolicies *policiesOpt /* NULL for none */
-)
-{
- NSSCertificate *rvCert = NULL;
- PRStatus nssrv;
- struct get_best_cert_arg_str best;
- CK_ATTRIBUTE nick_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_LABEL, NULL, 0 }
- };
- CK_ULONG ctsize;
- nssList *nameList;
- /* set up the search template */
- ctsize = (CK_ULONG)(sizeof(nick_template) / sizeof(nick_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(nick_template, 0, &g_ck_class_cert);
- nick_template[1].pValue = (CK_VOID_PTR)name;
- nick_template[1].ulValueLen = (CK_ULONG)nssUTF8_Length(name, &nssrv);
- /* set the criteria for determining the best cert */
- best.td = td;
- best.cert = NULL;
- best.time = (timeOpt) ? timeOpt : NSSTime_Now(NULL);
- best.usage = usage;
- best.policies = policiesOpt;
- /* find all matching certs in the cache */
- nameList = nssList_Create(NULL, PR_FALSE);
- (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList);
- best.cached = nameList;
- /* now find the best cert on tokens */
- rvCert = find_best_cert_for_template(td, token,
- &best, nick_template, ctsize);
- if (!rvCert) {
- /* This is to workaround the fact that PKCS#11 doesn't specify
- * whether the '\0' should be included. XXX Is that still true?
- */
- nick_template[1].ulValueLen++;
- rvCert = find_best_cert_for_template(td, token,
- &best, nick_template, ctsize);
- }
- nssList_Destroy(nameList);
- return rvCert;
-}
-
NSS_IMPLEMENT NSSCertificate *
NSSTrustDomain_FindBestCertificateByNickname
(
@@ -580,23 +430,12 @@ NSSTrustDomain_FindBestCertificateByNickname
NSSPolicies *policiesOpt /* NULL for none */
)
{
- NSSCertificate *rvCert = NULL;
PRStatus nssrv;
+ NSSToken *token;
+ nssTokenCertSearch search;
struct get_best_cert_arg_str best;
- CK_ATTRIBUTE nick_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_LABEL, NULL, 0 }
- };
- CK_ULONG ctsize;
nssList *nameList;
- /* set up the search template */
- ctsize = (CK_ULONG)(sizeof(nick_template) / sizeof(nick_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(nick_template, 0, &g_ck_class_cert);
- nick_template[1].pValue = (CK_VOID_PTR)name;
- nick_template[1].ulValueLen = (CK_ULONG)nssUTF8_Length(name, &nssrv);
/* set the criteria for determining the best cert */
- best.td = td;
best.cert = NULL;
best.time = (timeOpt) ? timeOpt : NSSTime_Now(NULL);
best.usage = usage;
@@ -604,62 +443,26 @@ NSSTrustDomain_FindBestCertificateByNickname
/* find all matching certs in the cache */
nameList = nssList_Create(NULL, PR_FALSE);
(void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList);
- best.cached = nameList;
- /* now find the best cert on tokens */
- rvCert = find_best_cert_for_template(td, NULL,
- &best, nick_template, ctsize);
- if (!rvCert) {
- /* This is to workaround the fact that PKCS#11 doesn't specify
- * whether the '\0' should be included. XXX Is that still true?
- */
- nick_template[1].ulValueLen++;
- rvCert = find_best_cert_for_template(td, NULL,
- &best, nick_template, ctsize);
+ /* set the search criteria */
+ search.callback = get_best_cert;
+ search.cbarg = &best;
+ search.cached = nameList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ /* traverse the tokens */
+ for (token = (NSSToken *)nssListIterator_Start(td->tokens);
+ token != (NSSToken *)NULL;
+ token = (NSSToken *)nssListIterator_Next(td->tokens))
+ {
+ nssrv = nssToken_TraverseCertificatesByNickname(token, NULL,
+ name, &search);
}
+ nssListIterator_Finish(td->tokens);
nssList_Destroy(nameList);
- return rvCert;
-}
-
-/* XXX
- * This is really a hack for PK11_ calls that want to specify the token to
- * do lookups on (see PK11_FindCertsFromNickname). I don't think this
- * is something we want to keep.
- */
-NSS_IMPLEMENT NSSCertificate **
-nssTrustDomain_FindCertificatesByNicknameForToken
-(
- NSSTrustDomain *td,
- NSSToken *token,
- NSSUTF8 *name,
- NSSCertificate *rvOpt[],
- PRUint32 maximumOpt, /* 0 for no max */
- NSSArena *arenaOpt
-)
-{
- NSSCertificate **rvCerts = NULL;
- PRStatus nssrv;
- CK_ATTRIBUTE nick_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_LABEL, NULL, 0 }
- };
- nssList *nickCerts;
- struct collect_arg_str ca;
- CK_ULONG ctsize;
- ctsize = (CK_ULONG)(sizeof(nick_template) / sizeof(nick_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(nick_template, 0, &g_ck_class_cert);
- nick_template[1].pValue = (CK_VOID_PTR)name;
- nick_template[1].ulValueLen = (CK_ULONG)nssUTF8_Length(name, &nssrv);
- nickCerts = nssList_Create(NULL, PR_FALSE);
- (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nickCerts);
- ca.list = nickCerts;
- ca.maximum = maximumOpt;
- ca.arena = arenaOpt;
- ca.rvOpt = rvOpt;
- rvCerts = find_all_certs_for_template(td, token,
- &ca, nick_template, ctsize);
- nssList_Destroy(nickCerts);
- return rvCerts;
+ if (best.cert) {
+ nssTrustDomain_AddCertsToCache(td, &best.cert, 1);
+ }
+ return best.cert;
}
NSS_IMPLEMENT NSSCertificate **
@@ -673,28 +476,45 @@ NSSTrustDomain_FindCertificatesByNickname
)
{
NSSCertificate **rvCerts = NULL;
+ NSSToken *token;
+ PRUint32 count;
PRStatus nssrv;
- CK_ATTRIBUTE nick_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_LABEL, NULL, 0 }
- };
- nssList *nickCerts;
+ nssList *nameList;
struct collect_arg_str ca;
- CK_ULONG ctsize;
- ctsize = (CK_ULONG)(sizeof(nick_template) / sizeof(nick_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(nick_template, 0, &g_ck_class_cert);
- nick_template[1].pValue = (CK_VOID_PTR)name;
- nick_template[1].ulValueLen = (CK_ULONG)nssUTF8_Length(name, &nssrv);
- nickCerts = nssList_Create(NULL, PR_FALSE);
- (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nickCerts);
- ca.list = nickCerts;
+ nssTokenCertSearch search;
+ /* set up the collection */
+ nameList = nssList_Create(NULL, PR_FALSE);
+ (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList);
+ ca.list = nameList;
ca.maximum = maximumOpt;
- ca.arena = arenaOpt;
- ca.rvOpt = rvOpt;
- rvCerts = find_all_certs_for_template(td, NULL,
- &ca, nick_template, ctsize);
- nssList_Destroy(nickCerts);
+ /* set the search criteria */
+ search.callback = collect_certs;
+ search.cbarg = &ca;
+ search.cached = nameList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ /* traverse the tokens */
+ for (token = (NSSToken *)nssListIterator_Start(td->tokens);
+ token != (NSSToken *)NULL;
+ token = (NSSToken *)nssListIterator_Next(td->tokens))
+ {
+ nssrv = nssToken_TraverseCertificatesByNickname(token, NULL,
+ name, &search);
+ }
+ 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);
return rvCerts;
}
@@ -708,44 +528,29 @@ NSSTrustDomain_FindCertificateByIssuerAndSerialNumber
{
NSSCertificate *rvCert = NULL;
NSSToken *tok;
- CK_ULONG ctsize;
- CK_OBJECT_HANDLE object;
- CK_ATTRIBUTE cert_template[] = {
- { CKA_CLASS, NULL, 0 },
- { CKA_ISSUER, NULL, 0 },
- { CKA_SERIAL_NUMBER, NULL, 0 }
- };
- ctsize = sizeof(cert_template) / sizeof(cert_template[0]);
- /* Set the unique id */
- NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert);
- NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 1, issuer);
- NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 2, serialNumber);
/* Try the cache */
rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td,
issuer,
serialNumber);
- if (!rvCert) {
- /* Not cached, look for it on tokens */
- for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
- tok != (NSSToken *)NULL;
- tok = (NSSToken *)nssListIterator_Next(td->tokens))
- {
- object = nssToken_FindObjectByTemplate(tok, NULL,
- cert_template, ctsize);
- if (object != CK_INVALID_HANDLE) {
- /* Could not find cert, so create it */
- rvCert = nssCertificate_CreateFromHandle(NULL, object,
- tok->defaultSession,
- tok->slot);
- if (rvCert) {
- /* cache it */
- /*nssTrustDomain_AddCertsToCache(td, &rvCert, 1);*/
- }
- break;
- }
+ if (rvCert) {
+ 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))
+ {
+ rvCert = nssToken_FindCertificateByIssuerAndSerialNumber(tok,
+ NULL,
+ issuer,
+ serialNumber);
+ if (rvCert) {
+ /* cache it */
+ nssTrustDomain_AddCertsToCache(td, &rvCert, 1);
+ break;
}
- nssListIterator_Finish(td->tokens);
}
+ nssListIterator_Finish(td->tokens);
return rvCert;
}
@@ -759,31 +564,39 @@ NSSTrustDomain_FindBestCertificateBySubject
NSSPolicies *policiesOpt
)
{
- NSSCertificate *rvCert = NULL;
+ PRStatus nssrv;
+ NSSToken *token;
nssList *subjectList;
- CK_ATTRIBUTE subj_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_SUBJECT, NULL, 0 }
- };
struct get_best_cert_arg_str best;
- CK_ULONG ctsize;
- ctsize = (CK_ULONG)(sizeof(subj_template) / sizeof(subj_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(subj_template, 0, &g_ck_class_cert);
- NSS_CK_SET_ATTRIBUTE_ITEM(subj_template, 1, subject);
- best.td = td;
+ nssTokenCertSearch search;
+ /* set the criteria for determining the best cert */
best.cert = NULL;
best.time = (timeOpt) ? timeOpt : NSSTime_Now(NULL);
best.usage = usage;
best.policies = policiesOpt;
+ /* find all matching certs in the cache */
subjectList = nssList_Create(NULL, PR_FALSE);
(void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList);
- best.cached = subjectList;
- /* now find the best cert on tokens */
- rvCert = find_best_cert_for_template(td, NULL,
- &best, subj_template, ctsize);
+ /* set the search criteria */
+ search.callback = get_best_cert;
+ search.cbarg = &best;
+ search.cached = subjectList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ /* traverse the tokens */
+ for (token = (NSSToken *)nssListIterator_Start(td->tokens);
+ token != (NSSToken *)NULL;
+ token = (NSSToken *)nssListIterator_Next(td->tokens))
+ {
+ nssrv = nssToken_TraverseCertificatesBySubject(token, NULL,
+ subject, &search);
+ }
+ nssListIterator_Finish(td->tokens);
nssList_Destroy(subjectList);
- return rvCert;
+ if (best.cert) {
+ nssTrustDomain_AddCertsToCache(td, &best.cert, 1);
+ }
+ return best.cert;
}
NSS_IMPLEMENT NSSCertificate **
@@ -796,26 +609,45 @@ NSSTrustDomain_FindCertificatesBySubject
NSSArena *arenaOpt
)
{
+ PRStatus nssrv;
NSSCertificate **rvCerts = NULL;
+ NSSToken *token;
+ PRUint32 count;
nssList *subjectList;
struct collect_arg_str ca;
- CK_ATTRIBUTE subj_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_SUBJECT, NULL, 0 }
- };
- CK_ULONG ctsize;
- ctsize = (CK_ULONG)(sizeof(subj_template) / sizeof(subj_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(subj_template, 0, &g_ck_class_cert);
- NSS_CK_SET_ATTRIBUTE_ITEM(subj_template, 1, subject);
+ nssTokenCertSearch search;
+ /* set up the collection */
subjectList = nssList_Create(NULL, PR_FALSE);
(void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList);
ca.list = subjectList;
ca.maximum = maximumOpt;
- ca.arena = arenaOpt;
- ca.rvOpt = rvOpt;
- rvCerts = find_all_certs_for_template(td, NULL,
- &ca, subj_template, ctsize);
+ /* set the search criteria */
+ search.callback = collect_certs;
+ search.cbarg = &ca;
+ search.cached = subjectList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ /* traverse the tokens */
+ for (token = (NSSToken *)nssListIterator_Start(td->tokens);
+ token != (NSSToken *)NULL;
+ token = (NSSToken *)nssListIterator_Next(td->tokens))
+ {
+ nssrv = nssToken_TraverseCertificatesBySubject(token, NULL,
+ subject, &search);
+ }
+ 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);
+ }
+ nssTrustDomain_AddCertsToCache(td, rvCerts, count);
+ }
nssList_Destroy(subjectList);
return rvCerts;
}
@@ -857,39 +689,25 @@ NSSTrustDomain_FindCertificateByEncodedCertificate
{
NSSCertificate *rvCert = NULL;
NSSToken *tok;
- CK_ULONG ctsize;
- CK_OBJECT_HANDLE object;
- CK_ATTRIBUTE cert_template[] = {
- { CKA_CLASS, NULL, 0 },
- { CKA_VALUE, NULL, 0 }
- };
- ctsize = sizeof(cert_template) / sizeof(cert_template[0]);
- NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 0, &g_ck_class_cert);
- NSS_CK_SET_ATTRIBUTE_ITEM(cert_template, 1, encodedCertificate);
/* Try the cache */
rvCert = nssTrustDomain_GetCertByDERFromCache(td, encodedCertificate);
- if (!rvCert) {
- /* Not cached, look for it on tokens */
- for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
- tok != (NSSToken *)NULL;
- tok = (NSSToken *)nssListIterator_Next(td->tokens))
- {
- object = nssToken_FindObjectByTemplate(tok, NULL,
- cert_template, ctsize);
- if (object != CK_INVALID_HANDLE) {
- /* found it */
- rvCert = nssCertificate_CreateFromHandle(NULL, object,
- tok->defaultSession,
- tok->slot);
- if (rvCert) {
- /* cache it */
- /*nssTrustDomain_AddCertsToCache(td, &rvCert, 1);*/
- }
- break;
- }
+ if (rvCert) {
+ 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))
+ {
+ rvCert = nssToken_FindCertificateByEncodedCertificate(tok, NULL,
+ encodedCertificate);
+ if (rvCert) {
+ /* cache it */
+ nssTrustDomain_AddCertsToCache(td, &rvCert, 1);
+ break;
}
- nssListIterator_Finish(td->tokens);
}
+ nssListIterator_Finish(td->tokens);
return rvCert;
}
@@ -903,23 +721,12 @@ NSSTrustDomain_FindCertificateByEmail
NSSPolicies *policiesOpt
)
{
- NSSCertificate *rvCert = NULL;
PRStatus nssrv;
+ NSSToken *token;
struct get_best_cert_arg_str best;
- CK_ATTRIBUTE email_template[] =
- {
- { CKA_CLASS, NULL, 0 },
- { CKA_NETSCAPE_EMAIL, NULL, 0 }
- };
- CK_ULONG ctsize;
+ nssTokenCertSearch search;
nssList *emailList;
- /* set up the search template */
- ctsize = (CK_ULONG)(sizeof(email_template) / sizeof(email_template[0]));
- NSS_CK_SET_ATTRIBUTE_ITEM(email_template, 0, &g_ck_class_cert);
- email_template[1].pValue = (CK_VOID_PTR)email;
- email_template[1].ulValueLen = (CK_ULONG)nssUTF8_Length(email, &nssrv);
/* set the criteria for determining the best cert */
- best.td = td;
best.cert = NULL;
best.time = (timeOpt) ? timeOpt : NSSTime_Now(NULL);
best.usage = usage;
@@ -927,20 +734,26 @@ NSSTrustDomain_FindCertificateByEmail
/* find all matching certs in the cache */
emailList = nssList_Create(NULL, PR_FALSE);
(void)nssTrustDomain_GetCertsForEmailAddressFromCache(td, email, emailList);
- best.cached = emailList;
- /* now find the best cert on tokens */
- rvCert = find_best_cert_for_template(td, NULL,
- &best, email_template, ctsize);
- if (!rvCert) {
- /* This is to workaround the fact that PKCS#11 doesn't specify
- * whether the '\0' should be included. XXX Is that still true?
- */
- email_template[1].ulValueLen++;
- rvCert = find_best_cert_for_template(td, NULL,
- &best, email_template, ctsize);
+ /* set the search criteria */
+ search.callback = get_best_cert;
+ search.cbarg = &best;
+ search.cached = emailList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ /* traverse the tokens */
+ for (token = (NSSToken *)nssListIterator_Start(td->tokens);
+ token != (NSSToken *)NULL;
+ token = (NSSToken *)nssListIterator_Next(td->tokens))
+ {
+ nssrv = nssToken_TraverseCertificatesByEmail(token, NULL,
+ email, &search);
}
+ nssListIterator_Finish(td->tokens);
nssList_Destroy(emailList);
- return rvCert;
+ if (best.cert) {
+ nssTrustDomain_AddCertsToCache(td, &best.cert, 1);
+ }
+ return best.cert;
}
NSS_IMPLEMENT NSSCertificate **
@@ -1072,17 +885,26 @@ NSSTrustDomain_TraverseCertificates
)
{
PRStatus nssrv;
- NSSToken *tok;
-
- /* we need to lock the iterator */
- for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
- tok != (NSSToken *)NULL;
- tok = (NSSToken *)nssListIterator_Next(td->tokens))
+ NSSToken *token;
+ nssList *certList;
+ nssTokenCertSearch search;
+ (void *)nssTrustDomain_GetCertsFromCache(td, certList);
+ /* set the search criteria */
+ search.callback = callback;
+ search.cbarg = arg;
+ search.cached = certList;
+ search.trustDomain = td;
+ search.cryptoContext = NULL;
+ /* traverse the tokens */
+ for (token = (NSSToken *)nssListIterator_Start(td->tokens);
+ token != (NSSToken *)NULL;
+ token = (NSSToken *)nssListIterator_Next(td->tokens))
{
- nssrv = nssToken_TraverseCertificates(tok, NULL, callback, arg);
+ nssrv = nssToken_TraverseCertificates(token, NULL, &search);
}
nssListIterator_Finish(td->tokens);
- return NULL; /* should return array of nssrv's ? */
+ nssList_Destroy(certList);
+ return NULL;
}
NSS_IMPLEMENT PRStatus
@@ -1149,8 +971,18 @@ NSSTrustDomain_CreateCryptoContext
NSSCallback *uhhOpt
)
{
- nss_SetError(NSS_ERROR_NOT_FOUND);
- return NULL;
+ NSSArena *arena;
+ NSSCryptoContext *rvCC;
+ arena = NSSArena_Create();
+ if (!arena) {
+ return NULL;
+ }
+ rvCC = nss_ZNEW(arena, NSSCryptoContext);
+ if (!rvCC) {
+ return NULL;
+ }
+ rvCC->td = td;
+ return rvCC;
}
NSS_IMPLEMENT NSSCryptoContext *