summaryrefslogtreecommitdiff
path: root/security/nss/lib/dev
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/dev')
-rw-r--r--security/nss/lib/dev/ckhelper.c95
-rw-r--r--security/nss/lib/dev/ckhelper.h9
-rw-r--r--security/nss/lib/dev/dev.h56
-rw-r--r--security/nss/lib/dev/devm.h72
-rw-r--r--security/nss/lib/dev/devslot.c12
-rw-r--r--security/nss/lib/dev/devt.h7
-rw-r--r--security/nss/lib/dev/devtm.h2
-rw-r--r--security/nss/lib/dev/devtoken.c139
-rw-r--r--security/nss/lib/dev/devutil.c769
-rw-r--r--security/nss/lib/dev/manifest.mn1
10 files changed, 1006 insertions, 156 deletions
diff --git a/security/nss/lib/dev/ckhelper.c b/security/nss/lib/dev/ckhelper.c
index c07afd649..3e3c41ce3 100644
--- a/security/nss/lib/dev/ckhelper.c
+++ b/security/nss/lib/dev/ckhelper.c
@@ -357,14 +357,10 @@ nssCryptokiCertificate_GetAttributes
return PR_SUCCESS;
}
-#ifdef PURE_STAN_BUILD
status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt,
certObject, CKO_CERTIFICATE,
cert_template, template_size);
if (status != PR_SUCCESS) {
-#else
- if (PR_TRUE) {
-#endif
session = sessionOpt ?
sessionOpt :
@@ -577,15 +573,11 @@ nssCryptokiTrust_GetAttributes
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust);
NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size);
-#ifdef PURE_STAN_BUILD
status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL,
trustObject,
CKO_NETSCAPE_TRUST,
trust_template, trust_size);
if (status != PR_SUCCESS) {
-#else
- if (PR_TRUE) {
-#endif
session = sessionOpt ?
sessionOpt :
nssToken_GetDefaultSession(trustObject->token);
@@ -607,16 +599,15 @@ nssCryptokiTrust_GetAttributes
return PR_SUCCESS;
}
-#ifdef PURE_STAN_BUILD
NSS_IMPLEMENT PRStatus
nssCryptokiCRL_GetAttributes
(
nssCryptokiObject *crlObject,
nssSession *sessionOpt,
NSSArena *arenaOpt,
- NSSItem *crl,
- NSSItem *krl,
- NSSItem *url
+ NSSItem *encodingOpt,
+ NSSUTF8 **urlOpt,
+ PRBool *isKRLOpt
)
{
PRStatus status;
@@ -626,12 +617,19 @@ nssCryptokiCRL_GetAttributes
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE crl_template[5];
CK_ULONG crl_size;
+ PRUint32 i;
NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken);
- NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
- NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_KRL);
- NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_URL);
+ if (encodingOpt) {
+ NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
+ }
+ if (urlOpt) {
+ NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_URL);
+ }
+ if (isKRLOpt) {
+ NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_KRL);
+ }
NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
@@ -653,10 +651,69 @@ nssCryptokiCRL_GetAttributes
}
}
- NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[0], crl);
- NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[1], krl);
- NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[2], url);
+ i=0;
+ if (encodingOpt) {
+ NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); i++;
+ }
+ if (urlOpt) {
+ NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt); i++;
+ }
+ if (isKRLOpt) {
+ NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); i++;
+ }
return PR_SUCCESS;
}
-#endif /* PURE_STAN_BUILD */
+
+NSS_IMPLEMENT PRStatus
+nssCryptokiPrivateKey_SetCertificate
+(
+ nssCryptokiObject *keyObject,
+ nssSession *sessionOpt,
+ NSSUTF8 *nickname,
+ NSSItem *id,
+ NSSDER *subject
+)
+{
+ CK_RV ckrv;
+ CK_ATTRIBUTE_PTR attr;
+ CK_ATTRIBUTE key_template[3];
+ CK_ULONG key_size;
+ void *epv = nssToken_GetCryptokiEPV(keyObject->token);
+ nssSession *session;
+ NSSToken *token = keyObject->token;
+ nssSession *defaultSession = nssToken_GetDefaultSession(token);
+ PRBool createdSession = PR_FALSE;
+
+ NSS_CK_TEMPLATE_START(key_template, attr, key_size);
+ NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
+ NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
+ NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
+ NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size);
+
+ if (sessionOpt) {
+ if (!nssSession_IsReadWrite(sessionOpt)) {
+ return PR_FAILURE;
+ } else {
+ session = sessionOpt;
+ }
+ } else if (nssSession_IsReadWrite(defaultSession)) {
+ session = defaultSession;
+ } else {
+ NSSSlot *slot = nssToken_GetSlot(token);
+ session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
+ createdSession = PR_TRUE;
+ nssSlot_Destroy(slot);
+ }
+
+ ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle,
+ keyObject->handle,
+ key_template,
+ key_size);
+
+ if (createdSession) {
+ nssSession_Destroy(session);
+ }
+
+ return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
+}
diff --git a/security/nss/lib/dev/ckhelper.h b/security/nss/lib/dev/ckhelper.h
index fc64ea9b7..9beab920d 100644
--- a/security/nss/lib/dev/ckhelper.h
+++ b/security/nss/lib/dev/ckhelper.h
@@ -109,6 +109,15 @@ NSS_EXTERN_DATA const NSSItem g_ck_class_privkey;
(item)->size = 0; \
}
+#define NSS_CK_ATTRIBUTE_TO_BOOL(attrib, boolvar) \
+ if ((attrib)->ulValueLen > 0) { \
+ if (*((CK_BBOOL*)(attrib)->pValue) == CK_TRUE) { \
+ boolvar = PR_TRUE; \
+ } else { \
+ boolvar = PR_FALSE; \
+ } \
+ }
+
/* NSS_CK_ATTRIBUTE_TO_UTF8(attrib, str)
*
* Convert a CK_ATTRIBUTE to a string.
diff --git a/security/nss/lib/dev/dev.h b/security/nss/lib/dev/dev.h
index 2e7bc4cdd..612c0c018 100644
--- a/security/nss/lib/dev/dev.h
+++ b/security/nss/lib/dev/dev.h
@@ -377,6 +377,7 @@ nssSlot_CreateSession
* nssToken_FindTrustObjects
* nssToken_FindTrustForCertificate
* nssToken_FindCRLs
+ * nssToken_FindCRLsBySubject
* nssToken_FindPrivateKeys
* nssToken_FindPrivateKeyByID
* nssToken_Digest
@@ -577,6 +578,17 @@ nssToken_FindCRLs
);
NSS_EXTERN nssCryptokiObject **
+nssToken_FindCRLsBySubject
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSDER *subject,
+ nssTokenSearchType searchType,
+ PRUint32 maximumOpt,
+ PRStatus *statusOpt
+);
+
+NSS_EXTERN nssCryptokiObject **
nssToken_FindPrivateKeys
(
NSSToken *token,
@@ -740,9 +752,23 @@ nssCryptokiCRL_GetAttributes
nssCryptokiObject *crlObject,
nssSession *sessionOpt,
NSSArena *arenaOpt,
- NSSItem *crl,
- NSSItem *krl,
- NSSItem *url
+ NSSItem *encodingOpt,
+ NSSUTF8 **urlOpt,
+ PRBool *isKRLOpt
+);
+
+/* I'm including this to handle import of certificates in NSS 3.5. This
+ * function will set the cert-related attributes of a key, in order to
+ * associate it with a cert. Does it stay like this for 4.0?
+ */
+NSS_EXTERN PRStatus
+nssCryptokiPrivateKey_SetCertificate
+(
+ nssCryptokiObject *keyObject,
+ nssSession *sessionOpt,
+ NSSUTF8 *nickname,
+ NSSItem *id,
+ NSSDER *subject
);
NSS_EXTERN void
@@ -915,30 +941,6 @@ nssToken_GetDefaultSession
);
NSS_EXTERN PRStatus
-nssToken_SetTrustCache
-(
- NSSToken *tok
-);
-
-NSS_EXTERN PRStatus
-nssToken_SetCrlCache
-(
- NSSToken *tok
-);
-
-NSS_EXTERN PRBool
-nssToken_HasCrls
-(
- NSSToken *tok
-);
-
-NSS_EXTERN PRStatus
-nssToken_SetHasCrls
-(
- NSSToken *tok
-);
-
-NSS_EXTERN PRStatus
nssToken_GetTrustOrder
(
NSSToken *tok
diff --git a/security/nss/lib/dev/devm.h b/security/nss/lib/dev/devm.h
index 9b2bf6c8c..9e62df1a1 100644
--- a/security/nss/lib/dev/devm.h
+++ b/security/nss/lib/dev/devm.h
@@ -142,6 +142,78 @@ nssCryptokiObject_Create
CK_OBJECT_HANDLE h
);
+NSS_EXTERN nssTokenObjectCache *
+nssTokenObjectCache_Create
+(
+ NSSToken *token,
+ PRBool cacheCerts,
+ PRBool cacheTrust,
+ PRBool cacheCRLs
+);
+
+NSS_EXTERN void
+nssTokenObjectCache_Destroy
+(
+ nssTokenObjectCache *cache
+);
+
+NSS_EXTERN PRBool
+nssTokenObjectCache_HaveObjectClass
+(
+ nssTokenObjectCache *cache,
+ CK_OBJECT_CLASS objclass
+);
+
+NSS_EXTERN nssCryptokiObject **
+nssTokenObjectCache_FindObjectsByTemplate
+(
+ nssTokenObjectCache *cache,
+ CK_OBJECT_CLASS objclass,
+ CK_ATTRIBUTE_PTR otemplate,
+ CK_ULONG otlen,
+ PRUint32 maximumOpt
+);
+
+NSS_EXTERN PRStatus
+nssTokenObjectCache_GetObjectAttributes
+(
+ nssTokenObjectCache *cache,
+ NSSArena *arenaOpt,
+ nssCryptokiObject *object,
+ CK_OBJECT_CLASS objclass,
+ CK_ATTRIBUTE_PTR atemplate,
+ CK_ULONG atlen
+);
+
+NSS_EXTERN PRStatus
+nssTokenObjectCache_ImportObject
+(
+ nssTokenObjectCache *cache,
+ nssCryptokiObject *object,
+ CK_OBJECT_CLASS objclass,
+ CK_ATTRIBUTE_PTR ot,
+ CK_ULONG otlen
+);
+
+NSS_EXTERN PRStatus
+nssTokenObjectCache_RemoveObject
+(
+ nssTokenObjectCache *cache,
+ nssCryptokiObject *object
+);
+
+/* XXX allows peek back into token */
+NSS_EXTERN PRStatus
+nssToken_GetCachedObjectAttributes
+(
+ NSSToken *token,
+ NSSArena *arenaOpt,
+ nssCryptokiObject *object,
+ CK_OBJECT_CLASS objclass,
+ CK_ATTRIBUTE_PTR atemplate,
+ CK_ULONG atlen
+);
+
/* PKCS#11 stores strings in a fixed-length buffer padded with spaces. This
* function gets the length of the actual string.
*/
diff --git a/security/nss/lib/dev/devslot.c b/security/nss/lib/dev/devslot.c
index 9ee9e4e1f..6950256ad 100644
--- a/security/nss/lib/dev/devslot.c
+++ b/security/nss/lib/dev/devslot.c
@@ -177,11 +177,13 @@ nssSlot_Destroy
)
{
#ifdef PURE_STAN_BUILD
- PR_AtomicDecrement(&slot->base.refCount);
- if (slot->base.refCount == 0) {
- nssToken_Destroy(slot->token);
- nssModule_DestroyFromSlot(slot->module, slot);
- return nssArena_Destroy(slot->base.arena);
+ if (slot) {
+ PR_AtomicDecrement(&slot->base.refCount);
+ if (slot->base.refCount == 0) {
+ nssToken_Destroy(slot->token);
+ nssModule_DestroyFromSlot(slot->module, slot);
+ return nssArena_Destroy(slot->base.arena);
+ }
}
#endif
return PR_SUCCESS;
diff --git a/security/nss/lib/dev/devt.h b/security/nss/lib/dev/devt.h
index 4d7b2feaf..10a7978c3 100644
--- a/security/nss/lib/dev/devt.h
+++ b/security/nss/lib/dev/devt.h
@@ -82,6 +82,8 @@ struct nssDeviceBaseStr
PRUint32 flags;
};
+typedef struct nssTokenObjectCacheStr nssTokenObjectCache;
+
/* XXX until devobject.c goes away */
struct NSSTokenStr
{
@@ -93,12 +95,9 @@ struct NSSTokenStr
nssSession *defaultSession;
NSSTrustDomain *trustDomain;
PRIntervalTime lastTime;
- PRBool hasNoTrust;
- PRBool hasNoCrls;
+ nssTokenObjectCache *cache;
#ifdef NSS_3_4_CODE
PK11SlotInfo *pk11slot;
- nssList *certList; /* local cache of certs for slow tokens */
- PRBool loggedIn;
#endif
};
diff --git a/security/nss/lib/dev/devtm.h b/security/nss/lib/dev/devtm.h
index c2f5df580..5e48c5d80 100644
--- a/security/nss/lib/dev/devtm.h
+++ b/security/nss/lib/dev/devtm.h
@@ -53,8 +53,6 @@ PR_BEGIN_EXTERN_C
#define MAX_LOCAL_CACHE_OBJECTS 10
-typedef struct nssTokenObjectCacheStr nssTokenObjectCache;
-
PR_END_EXTERN_C
#endif /* DEVTM_H */
diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c
index 52c3b9c4c..44a577f45 100644
--- a/security/nss/lib/dev/devtoken.c
+++ b/security/nss/lib/dev/devtoken.c
@@ -150,13 +150,13 @@ nssToken_Destroy
NSSToken *tok
)
{
-#ifdef PURE_STAN_BUILD
- PR_AtomicDecrement(&tok->base.refCount);
- if (tok->base.refCount == 0) {
- nssTokenObjectCache_Destroy(tok->cache);
- return nssArena_Destroy(tok->base.arena);
+ if (tok) {
+ PR_AtomicDecrement(&tok->base.refCount);
+ if (tok->base.refCount == 0) {
+ nssTokenObjectCache_Destroy(tok->cache);
+ return nssArena_Destroy(tok->base.arena);
+ }
}
-#endif
return PR_SUCCESS;
}
@@ -268,11 +268,9 @@ nssToken_DeleteStoredObject
NSSToken *token = instance->token;
nssSession *session = NULL;
void *epv = nssToken_GetCryptokiEPV(instance->token);
-#ifdef PURE_STAN_BUILD
if (token->cache) {
status = nssTokenObjectCache_RemoveObject(token->cache, instance);
}
-#endif
if (instance->isTokenObject) {
if (nssSession_IsReadWrite(token->defaultSession)) {
session = token->defaultSession;
@@ -476,7 +474,6 @@ find_objects_by_template
CK_OBJECT_CLASS objclass;
nssCryptokiObject **objects = NULL;
PRUint32 i;
-#ifdef PURE_STAN_BUILD
for (i=0; i<otsize; i++) {
if (obj_template[i].type == CKA_CLASS) {
objclass = *(CK_OBJECT_CLASS *)obj_template[i].pValue;
@@ -495,7 +492,6 @@ find_objects_by_template
maximumOpt);
if (statusOpt) *statusOpt = PR_SUCCESS;
}
-#endif /* PURE_STAN_BUILD */
/* Either they are not cached, or cache failed; look on token. */
if (!objects) {
objects = find_objects(token, sessionOpt,
@@ -547,13 +543,11 @@ nssToken_ImportCertificate
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
/* Import the certificate onto the token */
rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize);
-#ifdef PURE_STAN_BUILD
if (rvObject && tok->cache) {
nssTokenObjectCache_ImportObject(tok->cache, rvObject,
CKO_CERTIFICATE,
cert_tmpl, ctsize);
}
-#endif
return rvObject;
}
@@ -1022,13 +1016,11 @@ nssToken_ImportTrust
NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize);
/* import the trust object onto the token */
object = import_object(tok, sessionOpt, trust_tmpl, tsize);
-#ifdef PURE_STAN_BUILD
if (object && tok->cache) {
nssTokenObjectCache_ImportObject(tok->cache, object,
CKO_CERTIFICATE,
trust_tmpl, tsize);
}
-#endif
return object;
}
@@ -1162,13 +1154,11 @@ nssToken_ImportCRL
/* import the crl object onto the token */
object = import_object(token, sessionOpt, crl_tmpl, crlsize);
-#ifdef PURE_STAN_BUILD
if (object && token->cache) {
nssTokenObjectCache_ImportObject(token->cache, object,
CKO_CERTIFICATE,
crl_tmpl, crlsize);
}
-#endif
return object;
}
@@ -1211,7 +1201,41 @@ nssToken_FindCRLs
return objects;
}
-#ifdef PURE_STAN_BUILD
+NSS_IMPLEMENT nssCryptokiObject **
+nssToken_FindCRLsBySubject
+(
+ NSSToken *token,
+ nssSession *sessionOpt,
+ NSSDER *subject,
+ nssTokenSearchType searchType,
+ PRUint32 maximumOpt,
+ PRStatus *statusOpt
+)
+{
+ CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL;
+ CK_ATTRIBUTE_PTR attr;
+ CK_ATTRIBUTE crlobj_template[3];
+ CK_ULONG crlobj_size;
+ nssCryptokiObject **objects;
+ nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
+
+ NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size);
+ if (searchType == nssTokenSearchType_SessionOnly) {
+ NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
+ } else if (searchType == nssTokenSearchType_TokenOnly ||
+ searchType == nssTokenSearchType_TokenForced) {
+ NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
+ }
+ NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc);
+ NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
+ NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size);
+
+ objects = find_objects_by_template(token, session,
+ crlobj_template, crlobj_size,
+ maximumOpt, statusOpt);
+ return objects;
+}
+
NSS_IMPLEMENT PRStatus
nssToken_GetCachedObjectAttributes
(
@@ -1230,7 +1254,6 @@ nssToken_GetCachedObjectAttributes
object, objclass,
atemplate, atlen);
}
-#endif
NSS_IMPLEMENT NSSItem *
nssToken_Digest
@@ -1391,85 +1414,6 @@ nssToken_FinishDigest
return rvItem;
}
-#ifdef NSS_3_4_CODE
-
-NSS_IMPLEMENT PRStatus
-nssToken_SetTrustCache
-(
- NSSToken *token
-)
-{
- CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
- CK_ATTRIBUTE_PTR attr;
- CK_ATTRIBUTE tobj_template[2];
- CK_ULONG tobj_size;
- nssCryptokiObject **objects;
- nssSession *session = token->defaultSession;
-
- NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size);
- NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
- NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
- NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size);
-
- objects = find_objects_by_template(token, session,
- tobj_template, tobj_size, 1, NULL);
- token->hasNoTrust = PR_FALSE;
- if (objects) {
- nssCryptokiObjectArray_Destroy(objects);
- } else {
- token->hasNoTrust = PR_TRUE;
- }
- return PR_SUCCESS;
-}
-
-NSS_IMPLEMENT PRStatus
-nssToken_SetCrlCache
-(
- NSSToken *token
-)
-{
- CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_CRL;
- CK_ATTRIBUTE_PTR attr;
- CK_ATTRIBUTE tobj_template[2];
- CK_ULONG tobj_size;
- nssCryptokiObject **objects;
- nssSession *session = token->defaultSession;
-
- NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size);
- NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
- NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
- NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size);
-
- objects = find_objects_by_template(token, session,
- tobj_template, tobj_size, 1, NULL);
- token->hasNoCrls = PR_TRUE;
- if (objects) {
- nssCryptokiObjectArray_Destroy(objects);
- } else {
- token->hasNoCrls = PR_TRUE;
- }
- return PR_SUCCESS;
-}
-
-NSS_IMPLEMENT PRBool
-nssToken_HasCrls
-(
- NSSToken *tok
-)
-{
- return !tok->hasNoCrls;
-}
-
-NSS_IMPLEMENT PRStatus
-nssToken_SetHasCrls
-(
- NSSToken *tok
-)
-{
- tok->hasNoCrls = PR_FALSE;
- return PR_SUCCESS;
-}
-
NSS_IMPLEMENT PRBool
nssToken_IsPresent
(
@@ -1478,5 +1422,4 @@ nssToken_IsPresent
{
return nssSlot_IsTokenPresent(token->slot);
}
-#endif
diff --git a/security/nss/lib/dev/devutil.c b/security/nss/lib/dev/devutil.c
index fb97287e3..45ea9883d 100644
--- a/security/nss/lib/dev/devutil.c
+++ b/security/nss/lib/dev/devutil.c
@@ -539,9 +539,776 @@ nssSlotList_FindTokenByName
PZ_Unlock(slotList->lock);
return rvToken;
}
-
#endif /* PURE_STAN_BUILD */
+/* object cache for token */
+
+typedef struct
+{
+ NSSArena *arena;
+ nssCryptokiObject *object;
+ CK_ATTRIBUTE_PTR attributes;
+ CK_ULONG numAttributes;
+}
+nssCryptokiObjectAndAttributes;
+
+enum {
+ cachedCerts = 0,
+ cachedTrust = 1,
+ cachedCRLs = 2
+} cachedObjectType;
+
+struct nssTokenObjectCacheStr
+{
+ NSSToken *token;
+ PZLock *lock;
+ PRBool loggedIn;
+ PRBool doObjectType[3];
+ PRBool searchedObjectType[3];
+ nssCryptokiObjectAndAttributes **objects[3];
+};
+
+NSS_IMPLEMENT nssTokenObjectCache *
+nssTokenObjectCache_Create
+(
+ NSSToken *token,
+ PRBool cacheCerts,
+ PRBool cacheTrust,
+ PRBool cacheCRLs
+)
+{
+ nssTokenObjectCache *rvCache;
+ rvCache = nss_ZNEW(NULL, nssTokenObjectCache);
+ if (!rvCache) {
+ goto loser;
+ }
+ rvCache->lock = PZ_NewLock(nssILockOther); /* XXX */
+ if (!rvCache->lock) {
+ goto loser;
+ }
+ rvCache->doObjectType[cachedCerts] = cacheCerts;
+ rvCache->doObjectType[cachedTrust] = cacheTrust;
+ rvCache->doObjectType[cachedCRLs] = cacheCRLs;
+ rvCache->token = token; /* cache goes away with token */
+ return rvCache;
+loser:
+ return (nssTokenObjectCache *)NULL;
+}
+
+static void
+clear_cache
+(
+ nssTokenObjectCache *cache
+)
+{
+ nssCryptokiObjectAndAttributes **oa;
+ PRUint32 objectType;
+ for (objectType = cachedCerts; objectType <= cachedCRLs; objectType++) {
+ if (!cache->objects[objectType]) {
+ continue;
+ }
+ for (oa = cache->objects[objectType]; *oa; oa++) {
+ /* prevent the token from being destroyed */
+ (*oa)->object->token = NULL;
+ nssCryptokiObject_Destroy((*oa)->object);
+ nssArena_Destroy((*oa)->arena);
+ }
+ nss_ZFreeIf(cache->objects[objectType]);
+ cache->objects[objectType] = NULL;
+ cache->searchedObjectType[objectType] = PR_FALSE;
+ }
+}
+
+NSS_IMPLEMENT void
+nssTokenObjectCache_Destroy
+(
+ nssTokenObjectCache *cache
+)
+{
+ if (cache) {
+ clear_cache(cache);
+ PZ_DestroyLock(cache->lock);
+ nss_ZFreeIf(cache);
+ }
+}
+
+NSS_IMPLEMENT PRBool
+nssTokenObjectCache_HaveObjectClass
+(
+ nssTokenObjectCache *cache,
+ CK_OBJECT_CLASS objclass
+)
+{
+ PRBool haveIt;
+ PZ_Lock(cache->lock);
+ switch (objclass) {
+ case CKO_CERTIFICATE: haveIt = cache->doObjectType[cachedCerts]; break;
+ case CKO_NETSCAPE_TRUST: haveIt = cache->doObjectType[cachedTrust]; break;
+ case CKO_NETSCAPE_CRL: haveIt = cache->doObjectType[cachedCRLs]; break;
+ default: haveIt = PR_FALSE;
+ }
+ PZ_Unlock(cache->lock);
+ return haveIt;
+}
+
+static nssCryptokiObjectAndAttributes **
+get_object_and_attributes
+(
+ nssCryptokiObject **objects,
+ CK_ATTRIBUTE_TYPE *types,
+ PRUint32 numTypes,
+ PRBool *doObjects,
+ PRStatus *status
+)
+{
+ PRUint32 i, j, numObjects = 0;
+ nssCryptokiObject **op = objects;
+ nssCryptokiObjectAndAttributes **rvOandA = NULL;
+ NSSSlot *slot = NULL;
+ nssSession *session = NULL;
+ if (!objects) {
+ return (nssCryptokiObjectAndAttributes **)NULL;
+ }
+ while (*op++) numObjects++;
+ if (numObjects == MAX_LOCAL_CACHE_OBJECTS) {
+ /* Hit the maximum allowed, so don't use a cache (there are
+ * too many objects to make caching worthwhile, presumably, if
+ * the token can handle that many objects, it can handle searching.
+ */
+ *doObjects = PR_FALSE;
+ *status = PR_FAILURE;
+ } else {
+ if (numObjects == 0) {
+ /* The fact that there are no objects is cached, done */
+ return (nssCryptokiObjectAndAttributes **)NULL;
+ }
+ rvOandA = nss_ZNEWARRAY(NULL,
+ nssCryptokiObjectAndAttributes *,
+ numObjects + 1);
+ if (!rvOandA) {
+ goto loser;
+ }
+ slot = nssToken_GetSlot(objects[0]->token);
+ session = nssToken_GetDefaultSession(objects[0]->token);
+ for (i=0; i<numObjects; i++) {
+ NSSArena *arena;
+ arena = nssArena_Create();
+ if (!arena) {
+ goto loser;
+ }
+ rvOandA[i] = nss_ZNEW(arena, nssCryptokiObjectAndAttributes);
+ if (!rvOandA[i]) {
+ goto loser;
+ }
+ rvOandA[i]->arena = arena;
+ /* The cache is tied to the token, and therefore the objects
+ * in it should not hold references to the token.
+ */
+ nssToken_Destroy(objects[i]->token);
+ rvOandA[i]->object = objects[i];
+ rvOandA[i]->attributes = nss_ZNEWARRAY(arena,
+ CK_ATTRIBUTE, numTypes);
+ if (!rvOandA[i]->attributes) {
+ goto loser;
+ }
+ for (j=0; j<numTypes; j++) {
+ rvOandA[i]->attributes[j].type = types[j];
+ }
+ *status = nssCKObject_GetAttributes(objects[i]->handle,
+ rvOandA[i]->attributes,
+ numTypes,
+ arena,
+ session,
+ slot);
+ if (*status != PR_SUCCESS) {
+ goto loser;
+ }
+ rvOandA[i]->numAttributes = numTypes;
+ }
+ }
+ *status = PR_SUCCESS;
+ if (slot) {
+ nssSlot_Destroy(slot);
+ }
+ return rvOandA;
+loser:
+ *status = PR_FAILURE;
+ if (slot) {
+ nssSlot_Destroy(slot);
+ }
+ if (rvOandA) {
+ for (i=0; i<numObjects; i++) {
+ if (rvOandA[i]) {
+ nssArena_Destroy(rvOandA[i]->arena);
+ }
+ }
+ }
+ return (nssCryptokiObjectAndAttributes **)NULL;
+}
+
+/*
+ *
+ * State diagram for cache:
+ *
+ * token !present token removed
+ * +-------------------------+<----------------------+
+ * | ^ |
+ * v | |
+ * +----------+ slot friendly | token present +----------+
+ * | cache | -----------------> % ---------------> | cache |
+ * | unloaded | | loaded |
+ * +----------+ +----------+
+ * ^ | ^ |
+ * | | slot !friendly slot logged in | |
+ * | +-----------------------> % ----------------------+ |
+ * | | |
+ * | slot logged out v slot !friendly |
+ * +-----------------------------+<--------------------------+
+ *
+ */
+static PRBool
+search_for_objects
+(
+ nssTokenObjectCache *cache
+)
+{
+ PRBool doSearch = PR_FALSE;
+ NSSSlot *slot = nssToken_GetSlot(cache->token);
+ if (!nssSlot_IsTokenPresent(slot)) {
+ /* The token is no longer present, destroy any cached objects */
+ clear_cache(cache);
+ nssSlot_Destroy(slot);
+ return PR_FALSE;
+ }
+ /* Handle non-friendly slots (slots which require login for objects) */
+ if (!nssSlot_IsFriendly(slot)) {
+ if (nssSlot_IsLoggedIn(slot)) {
+ /* Either no state change, or went from !logged in -> logged in */
+ cache->loggedIn = PR_TRUE;
+ doSearch = PR_TRUE;
+ } else {
+ if (cache->loggedIn) {
+ /* went from logged in -> !logged in, destroy cached objects */
+ clear_cache(cache);
+ cache->loggedIn = PR_FALSE;
+ } /* else no state change, still not logged in, so exit */
+ }
+ } else {
+ /* slot is friendly, thus always available for search */
+ doSearch = PR_TRUE;
+ }
+ nssSlot_Destroy(slot);
+ return doSearch;
+}
+
+static PRStatus
+get_token_certs_for_cache
+(
+ nssTokenObjectCache *cache
+)
+{
+ PRStatus status;
+ nssCryptokiObject **objects;
+ CK_ATTRIBUTE_TYPE certAttr[] = {
+ CKA_CLASS,
+ CKA_TOKEN,
+ CKA_LABEL,
+ CKA_CERTIFICATE_TYPE,
+ CKA_ID,
+ CKA_VALUE,
+ CKA_ISSUER,
+ CKA_SERIAL_NUMBER,
+ CKA_SUBJECT,
+ CKA_NETSCAPE_EMAIL
+ };
+ PRUint32 numCertAttr = sizeof(certAttr) / sizeof(certAttr[0]);
+ if (!search_for_objects(cache) ||
+ cache->searchedObjectType[cachedCerts] ||
+ !cache->doObjectType[cachedCerts])
+ {
+ /* Either there was a state change that prevents a search
+ * (token removed or logged out), or the search was already done,
+ * or certs are not being cached.
+ */
+ return PR_SUCCESS;
+ }
+ objects = nssToken_FindCertificates(cache->token, NULL,
+ nssTokenSearchType_TokenForced,
+ MAX_LOCAL_CACHE_OBJECTS, &status);
+ if (status == PR_SUCCESS) {
+ PRBool *doIt = &cache->doObjectType[cachedCerts];
+ cache->objects[cachedCerts] = get_object_and_attributes(objects,
+ certAttr,
+ numCertAttr,
+ doIt,
+ &status);
+ if (status == PR_SUCCESS) {
+ nss_ZFreeIf(objects);
+ } else {
+ nssCryptokiObjectArray_Destroy(objects);
+ }
+ } else {
+ return status;
+ }
+ cache->searchedObjectType[cachedCerts] = PR_TRUE;
+ return PR_SUCCESS;
+}
+
+static PRStatus
+get_token_trust_for_cache
+(
+ nssTokenObjectCache *cache
+)
+{
+ PRStatus status;
+ nssCryptokiObject **objects;
+ CK_ATTRIBUTE_TYPE trustAttr[] = {
+ CKA_CLASS,
+ CKA_TOKEN,
+ CKA_LABEL,
+ CKA_CERT_SHA1_HASH,
+ CKA_CERT_MD5_HASH,
+ CKA_ISSUER,
+ CKA_SUBJECT,
+ CKA_TRUST_SERVER_AUTH,
+ CKA_TRUST_CLIENT_AUTH,
+ CKA_TRUST_EMAIL_PROTECTION,
+ CKA_TRUST_CODE_SIGNING
+ };
+ PRUint32 numTrustAttr = sizeof(trustAttr) / sizeof(trustAttr[0]);
+ if (!search_for_objects(cache) ||
+ cache->searchedObjectType[cachedTrust] ||
+ !cache->doObjectType[cachedTrust])
+ {
+ /* Either there was a state change that prevents a search
+ * (token removed or logged out), or the search was already done,
+ * or trust is not being cached.
+ */
+ return PR_SUCCESS;
+ }
+ objects = nssToken_FindTrustObjects(cache->token, NULL,
+ nssTokenSearchType_TokenForced,
+ MAX_LOCAL_CACHE_OBJECTS, &status);
+ if (status == PR_SUCCESS) {
+ PRBool *doIt = &cache->doObjectType[cachedTrust];
+ cache->objects[cachedTrust] = get_object_and_attributes(objects,
+ trustAttr,
+ numTrustAttr,
+ doIt,
+ &status);
+ if (status == PR_SUCCESS) {
+ nss_ZFreeIf(objects);
+ } else {
+ nssCryptokiObjectArray_Destroy(objects);
+ }
+ } else {
+ return status;
+ }
+ cache->searchedObjectType[cachedTrust] = PR_TRUE;
+ return PR_SUCCESS;
+}
+
+static PRStatus
+get_token_crls_for_cache
+(
+ nssTokenObjectCache *cache
+)
+{
+ PRStatus status;
+ nssCryptokiObject **objects;
+ CK_ATTRIBUTE_TYPE crlAttr[] = {
+ CKA_CLASS,
+ CKA_TOKEN,
+ CKA_LABEL,
+ CKA_VALUE,
+ CKA_SUBJECT,
+ CKA_NETSCAPE_KRL,
+ CKA_NETSCAPE_URL
+ };
+ PRUint32 numCRLAttr = sizeof(crlAttr) / sizeof(crlAttr[0]);
+ if (!search_for_objects(cache) ||
+ cache->searchedObjectType[cachedCRLs] ||
+ !cache->doObjectType[cachedCRLs])
+ {
+ /* Either there was a state change that prevents a search
+ * (token removed or logged out), or the search was already done,
+ * or CRLs are not being cached.
+ */
+ return PR_SUCCESS;
+ }
+ objects = nssToken_FindCRLs(cache->token, NULL,
+ nssTokenSearchType_TokenForced,
+ MAX_LOCAL_CACHE_OBJECTS, &status);
+ if (status == PR_SUCCESS) {
+ PRBool *doIt = &cache->doObjectType[cachedCRLs];
+ cache->objects[cachedCRLs] = get_object_and_attributes(objects,
+ crlAttr,
+ numCRLAttr,
+ doIt,
+ &status);
+ if (status == PR_SUCCESS) {
+ nss_ZFreeIf(objects);
+ } else {
+ nssCryptokiObjectArray_Destroy(objects);
+ }
+ } else {
+ return status;
+ }
+ cache->searchedObjectType[cachedCRLs] = PR_TRUE;
+ return PR_SUCCESS;
+}
+
+static nssCryptokiObject **
+find_objects_in_array
+(
+ nssCryptokiObjectAndAttributes **objArray,
+ CK_ATTRIBUTE_PTR ot,
+ CK_ULONG otlen,
+ PRUint32 maximumOpt
+)
+{
+ PRIntn oi;
+ PRUint32 i, j;
+ PRBool match;
+ NSSArena *arena;
+ PRUint32 size = 8;
+ PRUint32 numMatches = 0;
+ nssCryptokiObject **objects = NULL;
+ nssCryptokiObjectAndAttributes **matches = NULL;
+ if (!objArray) {
+ return (nssCryptokiObject **)NULL;
+ }
+ arena = nssArena_Create();
+ if (!arena) {
+ return (nssCryptokiObject **)NULL;
+ }
+ matches = nss_ZNEWARRAY(arena, nssCryptokiObjectAndAttributes *, size);
+ if (!matches) {
+ goto loser;
+ }
+ if (maximumOpt == 0) maximumOpt = ~0;
+ for (; *objArray && numMatches < maximumOpt; objArray++) {
+ nssCryptokiObjectAndAttributes *obj = *objArray;
+ for (i=0; i<otlen; i++) {
+ for (j=0; j<obj->numAttributes; j++) {
+ if (ot[i].type == obj->attributes[j].type) {
+ if (ot[i].ulValueLen == obj->attributes[j].ulValueLen &&
+ nsslibc_memequal(ot[i].pValue,
+ obj->attributes[j].pValue,
+ ot[i].ulValueLen, NULL))
+ {
+ match = PR_TRUE;
+ } else {
+ match = PR_FALSE;
+ }
+ break;
+ }
+ }
+ if (j == obj->numAttributes || !match) {
+ break;
+ }
+ }
+ if (match) {
+ matches[numMatches++] = obj;
+ if (numMatches == size) {
+ size *= 2;
+ matches = nss_ZREALLOCARRAY(matches,
+ nssCryptokiObjectAndAttributes *,
+ size);
+ if (!matches) {
+ goto loser;
+ }
+ }
+ }
+ }
+ if (numMatches > 0) {
+ objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numMatches + 1);
+ if (!objects) {
+ goto loser;
+ }
+ for (oi=0; oi<(PRIntn)numMatches; oi++) {
+ objects[oi] = nssCryptokiObject_Clone(matches[oi]->object);
+ if (!objects[oi]) {
+ goto loser;
+ }
+ }
+ }
+ nssArena_Destroy(arena);
+ return objects;
+loser:
+ if (objects) {
+ for (--oi; oi>=0; --oi) {
+ nssCryptokiObject_Destroy(objects[oi]);
+ }
+ }
+ nssArena_Destroy(arena);
+ return (nssCryptokiObject **)NULL;
+}
+
+NSS_IMPLEMENT nssCryptokiObject **
+nssTokenObjectCache_FindObjectsByTemplate
+(
+ nssTokenObjectCache *cache,
+ CK_OBJECT_CLASS objclass,
+ CK_ATTRIBUTE_PTR otemplate,
+ CK_ULONG otlen,
+ PRUint32 maximumOpt
+)
+{
+ PRStatus status = PR_FAILURE;
+ nssCryptokiObject **rvObjects = NULL;
+ PZ_Lock(cache->lock);
+ switch (objclass) {
+ case CKO_CERTIFICATE:
+ if (cache->doObjectType[cachedCerts]) {
+ status = get_token_certs_for_cache(cache);
+ if (status != PR_SUCCESS) {
+ goto finish;
+ }
+ rvObjects = find_objects_in_array(cache->objects[cachedCerts],
+ otemplate, otlen, maximumOpt);
+ }
+ break;
+ case CKO_NETSCAPE_TRUST:
+ if (cache->doObjectType[cachedTrust]) {
+ status = get_token_trust_for_cache(cache);
+ if (status != PR_SUCCESS) {
+ goto finish;
+ }
+ rvObjects = find_objects_in_array(cache->objects[cachedTrust],
+ otemplate, otlen, maximumOpt);
+ }
+ break;
+ case CKO_NETSCAPE_CRL:
+ if (cache->doObjectType[cachedCRLs]) {
+ status = get_token_crls_for_cache(cache);
+ if (status != PR_SUCCESS) {
+ goto finish;
+ }
+ rvObjects = find_objects_in_array(cache->objects[cachedCRLs],
+ otemplate, otlen, maximumOpt);
+ }
+ break;
+ default: break;
+ }
+finish:
+ PZ_Unlock(cache->lock);
+ return rvObjects;
+}
+
+NSS_IMPLEMENT PRStatus
+nssTokenObjectCache_GetObjectAttributes
+(
+ nssTokenObjectCache *cache,
+ NSSArena *arenaOpt,
+ nssCryptokiObject *object,
+ CK_OBJECT_CLASS objclass,
+ CK_ATTRIBUTE_PTR atemplate,
+ CK_ULONG atlen
+)
+{
+ PRUint32 i, j;
+ NSSArena *arena = NULL;
+ nssArenaMark *mark = NULL;
+ nssCryptokiObjectAndAttributes *cachedOA = NULL;
+ nssCryptokiObjectAndAttributes **oa = NULL;
+ PZ_Lock(cache->lock);
+ switch (objclass) {
+ case CKO_CERTIFICATE: oa = cache->objects[cachedCerts]; break;
+ case CKO_NETSCAPE_TRUST: oa = cache->objects[cachedTrust]; break;
+ case CKO_NETSCAPE_CRL: oa = cache->objects[cachedCRLs]; break;
+ default: goto loser;
+ }
+ if (!oa) {
+ goto loser;
+ }
+ for (; *oa; oa++) {
+ if (nssCryptokiObject_Equal((*oa)->object, object)) {
+ cachedOA = *oa;
+ break;
+ }
+ }
+ if (!cachedOA) {
+ goto loser; /* don't have this object */
+ }
+ if (arenaOpt) {
+ arena = arenaOpt;
+ mark = nssArena_Mark(arena);
+ }
+ for (i=0; i<atlen; i++) {
+ for (j=0; j<cachedOA->numAttributes; j++) {
+ if (atemplate[i].type == cachedOA->attributes[j].type) {
+ CK_ATTRIBUTE_PTR attr = &cachedOA->attributes[j];
+ if (cachedOA->attributes[j].ulValueLen == 0 ||
+ cachedOA->attributes[j].ulValueLen == (CK_ULONG)-1)
+ {
+ break; /* invalid attribute */
+ }
+ if (atemplate[i].ulValueLen > 0) {
+ if (atemplate[i].pValue == NULL ||
+ atemplate[i].ulValueLen < attr->ulValueLen)
+ {
+ goto loser;
+ }
+ } else {
+ atemplate[i].pValue = nss_ZAlloc(arena, attr->ulValueLen);
+ if (!atemplate[i].pValue) {
+ goto loser;
+ }
+ }
+ nsslibc_memcpy(atemplate[i].pValue,
+ attr->pValue, attr->ulValueLen);
+ atemplate[i].ulValueLen = attr->ulValueLen;
+ break;
+ }
+ }
+ if (j == cachedOA->numAttributes) {
+ atemplate[i].ulValueLen = (CK_ULONG)-1;
+ }
+ }
+ PZ_Unlock(cache->lock);
+ if (mark) {
+ nssArena_Unmark(arena, mark);
+ }
+ return PR_SUCCESS;
+loser:
+ PZ_Unlock(cache->lock);
+ if (mark) {
+ nssArena_Release(arena, mark);
+ }
+ return PR_FAILURE;
+}
+
+static nssCryptokiObjectAndAttributes *
+make_object_and_attr
+(
+ nssCryptokiObject *object,
+ CK_ATTRIBUTE_PTR ot,
+ CK_ULONG otlen
+)
+{
+ PRUint32 i;
+ NSSArena *arena;
+ nssCryptokiObjectAndAttributes *oa;
+ arena = nssArena_Create();
+ if (!arena) {
+ return (nssCryptokiObjectAndAttributes *)NULL;
+ }
+ oa = nss_ZNEW(arena, nssCryptokiObjectAndAttributes);
+ if (!oa) {
+ goto loser;
+ }
+ oa->object = object;
+ oa->arena = arena;
+ nssToken_Destroy(object->token);
+ oa->attributes = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, otlen);
+ if (!oa->attributes) {
+ goto loser;
+ }
+ for (i=0; i<otlen; i++) {
+ oa->attributes[i].pValue = nss_ZAlloc(arena, ot[i].ulValueLen);
+ if (!oa->attributes[i].pValue) {
+ goto loser;
+ }
+ nsslibc_memcpy(oa->attributes[i].pValue, ot[i].pValue,
+ ot[i].ulValueLen);
+ oa->attributes[i].ulValueLen = ot[i].ulValueLen;
+ }
+ oa->numAttributes = otlen;
+ return oa;
+loser:
+ nssArena_Destroy(arena);
+ return (nssCryptokiObjectAndAttributes *)NULL;
+}
+
+NSS_IMPLEMENT PRStatus
+nssTokenObjectCache_ImportObject
+(
+ nssTokenObjectCache *cache,
+ nssCryptokiObject *object,
+ CK_OBJECT_CLASS objclass,
+ CK_ATTRIBUTE_PTR ot,
+ CK_ULONG otlen
+)
+{
+ PRStatus status = PR_SUCCESS;
+ PRUint32 count;
+ nssCryptokiObjectAndAttributes **oa, ***otype;
+ PRUint32 objectType;
+ PZ_Lock(cache->lock);
+ switch (objclass) {
+ case CKO_CERTIFICATE: objectType = cachedCerts; break;
+ case CKO_NETSCAPE_TRUST: objectType = cachedTrust; break;
+ case CKO_NETSCAPE_CRL: objectType = cachedCRLs; break;
+ default: status = PR_FAILURE;
+ }
+ if (status != PR_SUCCESS || /* failed */
+ !cache->doObjectType[objectType] || /* not caching this kind */
+ !cache->searchedObjectType[objectType]) /* not cached yet anyway */
+ {
+ PZ_Unlock(cache->lock);
+ return status;
+ }
+ count = 0;
+ otype = &cache->objects[objectType]; /* index into array of types */
+ oa = *otype; /* the array of objects for this type */
+ while (oa && *oa++) count++;
+ if (count > 0) {
+ *otype = nss_ZREALLOCARRAY(*otype,
+ nssCryptokiObjectAndAttributes *,
+ count + 2);
+ } else {
+ *otype = nss_ZNEWARRAY(NULL, nssCryptokiObjectAndAttributes *, 2);
+ }
+ if (*otype) {
+ nssCryptokiObject *copyObject = nssCryptokiObject_Clone(object);
+ (*otype)[count] = make_object_and_attr(copyObject, ot, otlen);
+ status = ((*otype)[count] != NULL) ? PR_SUCCESS : PR_FAILURE;
+ } else {
+ status = PR_FAILURE;
+ }
+ PZ_Unlock(cache->lock);
+ return status;
+}
+
+NSS_IMPLEMENT PRStatus
+nssTokenObjectCache_RemoveObject
+(
+ nssTokenObjectCache *cache,
+ nssCryptokiObject *object
+)
+{
+ PRUint32 oType;
+ nssCryptokiObjectAndAttributes **oa, **swp = NULL;
+ PZ_Lock(cache->lock);
+ for (oType=0; oType<3; oType++) {
+ if (!cache->objects[oType]) {
+ continue;
+ }
+ for (oa = cache->objects[oType]; *oa; oa++) {
+ if (nssCryptokiObject_Equal((*oa)->object, object)) {
+ swp = oa; /* the entry to remove */
+ while (oa[1]) oa++; /* go to the tail */
+ (*swp)->object->token = NULL;
+ nssCryptokiObject_Destroy((*swp)->object);
+ nssArena_Destroy((*swp)->arena); /* destroy it */
+ *swp = *oa; /* swap the last with the removed */
+ *oa = NULL; /* null-terminate the array */
+ break;
+ }
+ }
+ if (swp) {
+ break;
+ }
+ }
+ PZ_Unlock(cache->lock);
+ if (swp && *swp == NULL) {
+ nss_ZFreeIf(swp); /* the only entry */
+ cache->objects[oType] = NULL;
+ }
+ return PR_SUCCESS;
+}
+
/* XXX of course this doesn't belong here */
NSS_IMPLEMENT NSSAlgorithmAndParameters *
NSSAlgorithmAndParameters_CreateSHA1Digest
diff --git a/security/nss/lib/dev/manifest.mn b/security/nss/lib/dev/manifest.mn
index df0151ef2..effab4805 100644
--- a/security/nss/lib/dev/manifest.mn
+++ b/security/nss/lib/dev/manifest.mn
@@ -58,6 +58,7 @@ CSRCS = \
# here is where the 3.4 glue code is added
ifndef PURE_STAN_BUILD
DEFINES = -DNSS_3_4_CODE
+PRIVATE_EXPORTS += devm.h devtm.h
endif
REQUIRES = security nspr