diff options
author | ian.mcgreer%sun.com <devnull@localhost> | 2002-04-18 17:30:05 +0000 |
---|---|---|
committer | ian.mcgreer%sun.com <devnull@localhost> | 2002-04-18 17:30:05 +0000 |
commit | e32e0c4d5cb51c5d0bab4d576d5204b15bf4a0ad (patch) | |
tree | f2a89821e8a62c949cadbcf3feeeec7cdf36624e | |
parent | c8f6e9bea58634c1eca5e72b021c0f11fd8fe36b (diff) | |
download | nss-hg-e32e0c4d5cb51c5d0bab4d576d5204b15bf4a0ad.tar.gz |
landing new smart card cache, bug 135429
-rw-r--r-- | security/nss/lib/dev/ckhelper.c | 95 | ||||
-rw-r--r-- | security/nss/lib/dev/ckhelper.h | 9 | ||||
-rw-r--r-- | security/nss/lib/dev/dev.h | 56 | ||||
-rw-r--r-- | security/nss/lib/dev/devm.h | 72 | ||||
-rw-r--r-- | security/nss/lib/dev/devslot.c | 12 | ||||
-rw-r--r-- | security/nss/lib/dev/devt.h | 7 | ||||
-rw-r--r-- | security/nss/lib/dev/devtm.h | 2 | ||||
-rw-r--r-- | security/nss/lib/dev/devtoken.c | 139 | ||||
-rw-r--r-- | security/nss/lib/dev/devutil.c | 769 | ||||
-rw-r--r-- | security/nss/lib/dev/manifest.mn | 1 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/dev3hack.c | 48 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/dev3hack.h | 6 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11cert.c | 552 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11slot.c | 9 | ||||
-rw-r--r-- | security/nss/lib/pki/certificate.c | 75 | ||||
-rw-r--r-- | security/nss/lib/pki/pki3hack.c | 251 | ||||
-rw-r--r-- | security/nss/lib/pki/pki3hack.h | 23 | ||||
-rw-r--r-- | security/nss/lib/pki/pkibase.c | 128 | ||||
-rw-r--r-- | security/nss/lib/pki/pkim.h | 66 | ||||
-rw-r--r-- | security/nss/lib/pki/pkit.h | 9 | ||||
-rw-r--r-- | security/nss/lib/pki/pkitm.h | 1 | ||||
-rw-r--r-- | security/nss/lib/pki/trustdomain.c | 92 |
22 files changed, 1686 insertions, 736 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 diff --git a/security/nss/lib/pk11wrap/dev3hack.c b/security/nss/lib/pk11wrap/dev3hack.c index 9994cb65b..06b279f95 100644 --- a/security/nss/lib/pk11wrap/dev3hack.c +++ b/security/nss/lib/pk11wrap/dev3hack.c @@ -43,9 +43,9 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "pkit.h" #endif /* PKIT_H */ -#ifndef DEVT_H -#include "devt.h" -#endif /* DEVT_H */ +#ifndef DEVM_H +#include "devm.h" +#endif /* DEVM_H */ #include "pki3hack.h" #include "dev3hack.h" @@ -117,11 +117,19 @@ static NSSSlot * nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSSlot *rvSlot; - rvSlot = nss_ZNEW(td->arena, NSSSlot); + NSSArena *arena; + arena = nssArena_Create(); + if (!arena) { + return NULL; + } + rvSlot = nss_ZNEW(arena, NSSSlot); if (!rvSlot) { + nssArena_Destroy(arena); return NULL; } rvSlot->base.refCount = 1; + rvSlot->base.lock = PZ_NewLock(nssILockOther); + rvSlot->base.arena = arena; rvSlot->pk11slot = nss3slot; rvSlot->epv = nss3slot->functionList; rvSlot->slotID = nss3slot->slotID; @@ -134,24 +142,41 @@ NSS_IMPLEMENT NSSToken * nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSToken *rvToken; - rvToken = nss_ZNEW(td->arena, NSSToken); + NSSArena *arena; + arena = nssArena_Create(); + if (!arena) { + return NULL; + } + rvToken = nss_ZNEW(arena, NSSToken); if (!rvToken) { + nssArena_Destroy(arena); return NULL; } rvToken->base.refCount = 1; + rvToken->base.lock = PZ_NewLock(nssILockOther); + rvToken->base.arena = arena; rvToken->pk11slot = nss3slot; rvToken->epv = nss3slot->functionList; rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); + /* if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) */ + /* The above test was used in 3.4, for this cache have it always on */ + if (PR_TRUE) { + rvToken->cache = nssTokenObjectCache_Create(rvToken, + PR_TRUE, PR_TRUE, PR_TRUE); + if (!rvToken->cache) { + nssArena_Destroy(arena); + return (NSSToken *)NULL; + } + } rvToken->trustDomain = td; /* Grab the token name from the PKCS#11 fixed-length buffer */ rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name,td->arena); rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot); rvToken->slot->token = rvToken; rvToken->defaultSession->slot = rvToken->slot; - rvToken->base.arena = td->arena; return rvToken; } @@ -195,8 +220,7 @@ nssToken_Refresh(NSSToken *token) nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); - nssToken_DestroyCertList(token, PR_TRUE); - return nssToken_LoadCerts(token); + return PR_SUCCESS; } NSS_IMPLEMENT PRStatus @@ -225,6 +249,14 @@ nssToken_GetTrustOrder return module->trustOrder; } +NSS_IMPLEMENT PRBool +nssSlot_IsLoggedIn +( + NSSSlot *slot +) +{ + return PK11_IsLoggedIn(slot->pk11slot, NULL); +} NSSTrustDomain * diff --git a/security/nss/lib/pk11wrap/dev3hack.h b/security/nss/lib/pk11wrap/dev3hack.h index 19f9bbb8b..d2e3ab4e1 100644 --- a/security/nss/lib/pk11wrap/dev3hack.h +++ b/security/nss/lib/pk11wrap/dev3hack.h @@ -58,12 +58,6 @@ void PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst); NSSToken * PK11Slot_GetNSSToken(PK11SlotInfo *sl); -NSS_EXTERN PRStatus -nssToken_LoadCerts(NSSToken *token); - -NSS_EXTERN void -nssToken_UpdateTrustForCerts(NSSToken *token); - PR_END_EXTERN_C #endif /* DEVNSS3HACK_H */ diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index c4cdca5c2..629940a96 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -1171,73 +1171,6 @@ PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, return objID; } -/* match all token certs with a nickname */ -static nssList * -filter_token_certs_nickname(NSSToken *token, NSSUTF8 *nickname) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRStatus nssrv; - nssList *rvList; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvList = nssList_Create(NULL, PR_FALSE); - if (!rvList) { - nssListIterator_Destroy(certs); - return NULL; - } - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - NSSUTF8 *tokenNick = nssCertificate_GetNickname(cert, token); - if (!tokenNick) continue; - if (nssUTF8_Equal(tokenNick, nickname, &nssrv)) { - nssList_Add(rvList, nssCertificate_AddRef(cert)); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - if (nssList_Count(rvList) == 0) { - nssList_Destroy(rvList); - rvList = NULL; - } - return rvList; -} - -/* match all token certs with an email address */ -static nssList * -filter_token_certs_email(NSSToken *token, NSSASCII7 *email) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRStatus nssrv; - nssList *rvList; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvList = nssList_Create(NULL, PR_FALSE); - if (!rvList) { - nssListIterator_Destroy(certs); - return NULL; - } - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - if (!cert->email) continue; - if (nssUTF8_Equal(cert->email, email, &nssrv)) { - nssList_Add(rvList, nssCertificate_AddRef(cert)); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - if (nssList_Count(rvList) == 0) { - nssList_Destroy(rvList); - rvList = NULL; - } - return rvList; -} - static void transfer_token_certs_to_collection(nssList *certList, NSSToken *token, nssPKIObjectCollection *collection) @@ -1329,49 +1262,37 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { if (!collection) { goto loser; } - if (!nssToken_SearchCerts(token, NULL)) { - certList = filter_token_certs_nickname(token, nickname); - transfer_token_certs_to_collection(certList, token, collection); - nssList_Destroy(certList); - } else { - certList = nssList_Create(NULL, PR_FALSE); - if (!certList) { - nssPKIObjectCollection_Destroy(collection); - goto loser; - } - (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, - nickname, - certList); - transfer_token_certs_to_collection(certList, token, collection); - instances = nssToken_FindCertificatesByNickname(token, - NULL, - nickname, - tokenOnly, - 0, - &status); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) { + nssPKIObjectCollection_Destroy(collection); + goto loser; } + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, + nickname, + certList); + transfer_token_certs_to_collection(certList, token, collection); + instances = nssToken_FindCertificatesByNickname(token, + NULL, + nickname, + tokenOnly, + 0, + &status); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); /* if it wasn't found, repeat the process for email address */ if (nssPKIObjectCollection_Count(collection) == 0) { - if (!nssToken_SearchCerts(token, NULL)) { - certList = filter_token_certs_email(token, nickname); - transfer_token_certs_to_collection(certList, token, collection); - nssList_Destroy(certList); - } else { - (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, + (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, nickname, certList); - transfer_token_certs_to_collection(certList, token, collection); - instances = nssToken_FindCertificatesByEmail(token, - NULL, - nickname, - tokenOnly, - 0, - &status); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); - } + transfer_token_certs_to_collection(certList, token, collection); + instances = nssToken_FindCertificatesByEmail(token, + NULL, + nickname, + tokenOnly, + 0, + &status); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); } certs = nssPKIObjectCollection_GetCertificates(collection, NULL, 0, NULL); @@ -1454,7 +1375,10 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { token = PK11Slot_GetNSSToken(slot); } if (token) { + PRStatus status; nssList *nameList; + nssCryptokiObject **instances; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; if (!PK11_IsFriendly(slot)) { if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) { PK11_FreeSlot(slot); @@ -1466,31 +1390,23 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { PK11_FreeSlot(slot); return NULL; } - if (!nssToken_SearchCerts(token, NULL)) { - nameList = filter_token_certs_nickname(token, nickname); - transfer_token_certs_to_collection(nameList, token, collection); - } else { - PRStatus status; - nssCryptokiObject **instances; - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - nameList = nssList_Create(NULL, PR_FALSE); - if (!nameList) { - PK11_FreeSlot(slot); - return NULL; - } - (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, - nickname, - nameList); - transfer_token_certs_to_collection(nameList, token, collection); - instances = nssToken_FindCertificatesByNickname(token, - NULL, - nickname, - tokenOnly, - 0, - &status); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); + nameList = nssList_Create(NULL, PR_FALSE); + if (!nameList) { + PK11_FreeSlot(slot); + return NULL; } + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, + nickname, + nameList); + transfer_token_certs_to_collection(nameList, token, collection); + instances = nssToken_FindCertificatesByNickname(token, + NULL, + nickname, + tokenOnly, + 0, + &status); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); nssList_Destroy(nameList); foundCerts = nssPKIObjectCollection_GetCertificates(collection, NULL, 0, NULL); @@ -1618,6 +1534,7 @@ PK11_MakeIDFromPubKey(SECItem *pubKeyData) { SECStatus PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) { +#ifdef NSS_CLASSIC int len = 0; SECItem *keyID = pk11_mkcertKeyID(cert); CK_ATTRIBUTE keyAttrs[] = { @@ -1748,14 +1665,6 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, } cert->trust = nssTrust_GetCERTCertTrustForCert(cert->nssCertificate, cert); token = PK11Slot_GetNSSToken(slot); - if (token->certList) { - /* create a persistent reference for the token */ - NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - nssCertificate_AddRef(cert->nssCertificate); - nssList_Add(token->certList, cert->nssCertificate); - /* and add the cert to the cache */ - nssTrustDomain_AddCertsToCache(td, &cert->nssCertificate, 1); - } done: if (derSerial.data) PORT_Free(derSerial.data); @@ -1765,7 +1674,74 @@ done: PORT_Free(certUsage); } return rv; +#else + PRStatus status; + NSSCertificate *c; + nssCryptokiObject *keyobj, *certobj; + NSSToken *token = PK11Slot_GetNSSToken(slot); + SECItem *keyID = pk11_mkcertKeyID(cert); + + if (keyID == NULL) { + goto loser; + } + + /* need to get the cert as a stan cert */ + if (cert->nssCertificate) { + c = cert->nssCertificate; + } else { + c = STAN_GetNSSCertificate(cert); + } + /* set the id for the cert */ + nssItem_Create(c->object.arena, &c->id, keyID->len, keyID->data); + if (!c->id.data) { + goto loser; + } + + if (key != CK_INVALID_HANDLE) { + /* create an object for the key, ... */ + keyobj = nss_ZNEW(NULL, nssCryptokiObject); + if (!keyobj) { + goto loser; + } + keyobj->token = nssToken_AddRef(token); + keyobj->handle = key; + keyobj->isTokenObject = PR_TRUE; + + /* ... in order to set matching attributes for the key */ + status = nssCryptokiPrivateKey_SetCertificate(keyobj, NULL, nickname, + &c->id, &c->subject); + nssCryptokiObject_Destroy(keyobj); + if (status != PR_SUCCESS) { + goto loser; + } + } + + /* do the token import */ + certobj = nssToken_ImportCertificate(token, NULL, + NSSCertificateType_PKIX, + &c->id, + nickname, + &c->encoding, + &c->issuer, + &c->subject, + &c->serial, + PR_TRUE); + if (!certobj) { + goto loser; + } + /* add the new instance to the cert, force an update of the + * CERTCertificate, and finish + */ + nssPKIObject_AddInstance(&c->object, certobj); + (void)STAN_ForceCERTCertificateUpdate(c); + SECITEM_FreeItem(keyID,PR_TRUE); + return SECSuccess; +loser: + SECITEM_FreeItem(keyID,PR_TRUE); + PORT_SetError(SEC_ERROR_ADDING_CERT); + return SECFailure; +#endif } /* @@ -2520,38 +2496,6 @@ PK11_TraverseCertsForSubject(CERTCertificate *cert, return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg); } -/* Find all certs with a given subject in the list of token certs */ -static nssList * -filter_token_certs_subject(NSSToken *token, NSSDER *subject) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRStatus nssrv; - nssList *rvList; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvList = nssList_Create(NULL, PR_FALSE); - if (!rvList) { - nssListIterator_Destroy(certs); - return NULL; - } - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - if (nssItem_Equal(&cert->subject, subject, &nssrv)) { - nssList_Add(rvList, nssCertificate_AddRef(cert)); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - if (nssList_Count(rvList) == 0) { - nssList_Destroy(rvList); - rvList = NULL; - } - return rvList; -} - SECStatus PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, SECStatus(* callback)(CERTCertificate*, void *), void *arg) @@ -2592,28 +2536,27 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, nssPKIObjectCollection *collection; nssCryptokiObject **instances; NSSCertificate **certs; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; td = STAN_GetDefaultTrustDomain(); NSSITEM_FROM_SECITEM(&subject, &cert->derSubject); token = PK11Slot_GetNSSToken(slot); collection = nssCertificateCollection_Create(td, NULL); - if (!nssToken_SearchCerts(token, NULL)) { - subjectList = filter_token_certs_subject(token, &subject); - transfer_token_certs_to_collection(subjectList, token, collection); - } else { - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - subjectList = nssList_Create(NULL, PR_FALSE); - if (!subjectList) { - return SECFailure; - } - (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, - subjectList); - transfer_token_certs_to_collection(subjectList, token, collection); - instances = nssToken_FindCertificatesBySubject(token, NULL, - &subject, - tokenOnly, 0, &nssrv); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); + if (!collection) { + return SECFailure; } + subjectList = nssList_Create(NULL, PR_FALSE); + if (!subjectList) { + nssPKIObjectCollection_Destroy(collection); + return SECFailure; + } + (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, + subjectList); + transfer_token_certs_to_collection(subjectList, token, collection); + instances = nssToken_FindCertificatesBySubject(token, NULL, + &subject, + tokenOnly, 0, &nssrv); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); nssList_Destroy(subjectList); certs = nssPKIObjectCollection_GetCertificates(collection, NULL, 0, NULL); @@ -2678,9 +2621,10 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, NSSUTF8 *nick; PRBool created = PR_FALSE; nssCryptokiObject **instances; - nssPKIObjectCollection *collection; + nssPKIObjectCollection *collection = NULL; NSSCertificate **certs; - nssList *nameList; + nssList *nameList = NULL; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; pk11cb.callback = callback; pk11cb.arg = arg; if (nickname->data[nickname->len-1] != '\0') { @@ -2693,23 +2637,20 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, td = STAN_GetDefaultTrustDomain(); token = PK11Slot_GetNSSToken(slot); collection = nssCertificateCollection_Create(td, NULL); - if (!nssToken_SearchCerts(token, NULL)) { - nameList = filter_token_certs_nickname(token, nick); - transfer_token_certs_to_collection(nameList, token, collection); - } else { - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - nameList = nssList_Create(NULL, PR_FALSE); - if (!nameList) { - return SECFailure; - } - (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList); - transfer_token_certs_to_collection(nameList, token, collection); - instances = nssToken_FindCertificatesByNickname(token, NULL, - nick, - tokenOnly, 0, &nssrv); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); + if (!collection) { + goto loser; + } + nameList = nssList_Create(NULL, PR_FALSE); + if (!nameList) { + goto loser; } + (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList); + transfer_token_certs_to_collection(nameList, token, collection); + instances = nssToken_FindCertificatesByNickname(token, NULL, + nick, + tokenOnly, 0, &nssrv); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); nssList_Destroy(nameList); certs = nssPKIObjectCollection_GetCertificates(collection, NULL, 0, NULL); @@ -2728,6 +2669,17 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, } if (created) nss_ZFreeIf(nick); return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; +loser: + if (created) { + nss_ZFreeIf(nick); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + if (nameList) { + nssList_Destroy(nameList); + } + return SECFailure; #endif } @@ -2768,27 +2720,23 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot, nssCryptokiObject **instances; nssPKIObjectCollection *collection; NSSCertificate **certs; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; tok = PK11Slot_GetNSSToken(slot); collection = nssCertificateCollection_Create(td, NULL); if (!collection) { return SECFailure; } - if (!nssToken_SearchCerts(tok, NULL)) { - certList = nssList_Clone(tok->certList); - transfer_token_certs_to_collection(certList, tok, collection); - } else { - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - certList = nssList_Create(NULL, PR_FALSE); - if (!certList) { - return SECFailure; - } - (void *)nssTrustDomain_GetCertsFromCache(td, certList); - transfer_token_certs_to_collection(certList, tok, collection); - instances = nssToken_FindCertificates(tok, NULL, - tokenOnly, 0, &nssrv); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) { + nssPKIObjectCollection_Destroy(collection); + return SECFailure; } + (void *)nssTrustDomain_GetCertsFromCache(td, certList); + transfer_token_certs_to_collection(certList, tok, collection); + instances = nssToken_FindCertificates(tok, NULL, + tokenOnly, 0, &nssrv); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); nssList_Destroy(certList); certs = nssPKIObjectCollection_GetCertificates(collection, NULL, 0, NULL); @@ -2809,29 +2757,6 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot, #endif } -static NSSCertificate * -filter_token_certs_DER(NSSToken *token, NSSDER *der) -{ - nssListIterator *certs; - NSSCertificate *cert, *rvCert; - PRStatus nssrv; - certs = nssList_CreateIterator(token->certList); - if (!certs) return NULL; - rvCert = NULL; - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - if (nssItem_Equal(&cert->encoding, der, &nssrv)) { - rvCert = nssCertificate_AddRef(cert); - break; - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); - return rvCert; -} - /* * return the certificate associated with a derCert */ @@ -2882,27 +2807,23 @@ PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert, return NULL; } } - if (!nssToken_SearchCerts(tok, NULL)) { - c = filter_token_certs_DER(tok, &derCert); - } else { - c = NSSTrustDomain_FindCertificateByEncodedCertificate(td, &derCert); - if (c) { - PRBool isToken = PR_FALSE; - NSSToken **tp; - NSSToken **tokens = nssPKIObject_GetTokens(&c->object, NULL); - if (tokens) { - for (tp = tokens; *tp; tp++) { - if (*tp == tok) { - isToken = PR_TRUE; - break; - } - } - if (!isToken) { - NSSCertificate_Destroy(c); - c = NULL; + c = NSSTrustDomain_FindCertificateByEncodedCertificate(td, &derCert); + if (c) { + PRBool isToken = PR_FALSE; + NSSToken **tp; + NSSToken **tokens = nssPKIObject_GetTokens(&c->object, NULL); + if (tokens) { + for (tp = tokens; *tp; tp++) { + if (*tp == tok) { + isToken = PR_TRUE; + break; } - nssTokenArray_Destroy(tokens); } + if (!isToken) { + NSSCertificate_Destroy(c); + c = NULL; + } + nssTokenArray_Destroy(tokens); } } if (c) { @@ -3602,6 +3523,7 @@ SECItem * PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, SECItem *name, int type, char **url) { +#ifdef NSS_CLASSIC CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; CK_ATTRIBUTE theTemplate[] = { { CKA_SUBJECT, NULL, 0 }, @@ -3635,9 +3557,6 @@ PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, /* loop through all the fortezza tokens */ for (le = list->head; le; le = le->next) { - if (le->slot->nssToken && !nssToken_HasCrls(le->slot->nssToken)) { - continue; - } crlh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize); if (crlh != CK_INVALID_HANDLE) { *slot = PK11_ReferenceSlot(le->slot); @@ -3684,12 +3603,68 @@ loser: } if (crlData[1].pValue) PORT_Free(crlData[1].pValue); return derCrl; +#else + NSSCRL **crls, **crlp, *crl; + NSSDER subject; + SECItem *rvItem; + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); + NSSITEM_FROM_SECITEM(&subject, name); + if (*slot) { + nssCryptokiObject **instances; + nssPKIObjectCollection *collection; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + NSSToken *token = PK11Slot_GetNSSToken(*slot); + collection = nssCRLCollection_Create(td, NULL); + if (!collection) { + return NULL; + } + instances = nssToken_FindCRLsBySubject(token, NULL, &subject, + tokenOnly, 0, NULL); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + } else { + crls = nssTrustDomain_FindCRLsBySubject(td, &subject); + } + if (!crls) { + return NULL; + } + crl = NULL; + for (crlp = crls; *crlp; crlp++) { + if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) || + ((*crlp)->isKRL && type != SEC_CRL_TYPE)) + { + crl = nssCRL_AddRef(*crlp); + break; + } + } + nssCRLArray_Destroy(crls); + if (!crl) { + return NULL; + } + *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot); + *crlHandle = crl->object.instances[0]->handle; + if (crl->url) { + *url = PORT_Strdup(crl->url); + } + rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size); + if (!rvItem) { + PORT_Free(*url); + nssCRL_Destroy(crl); + return NULL; + } + memcpy(rvItem->data, crl->encoding.data, crl->encoding.size); + nssCRL_Destroy(crl); + return rvItem; +#endif } CK_OBJECT_HANDLE PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, char *url, int type) { +#ifdef NSS_CLASSIC CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; CK_ATTRIBUTE theTemplate[] = { { CKA_SUBJECT, NULL, 0 }, @@ -3735,12 +3710,29 @@ PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, PK11_RestoreROSession(slot,rwsession); - if (slot->nssToken) { - nssToken_SetHasCrls(slot->nssToken); - } return crlh; -} +#else + NSSItem derCRL, derSubject; + NSSToken *token = PK11Slot_GetNSSToken(slot); + nssCryptokiObject *object; + PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE; + CK_OBJECT_HANDLE rvH; + NSSITEM_FROM_SECITEM(&derSubject, name); + NSSITEM_FROM_SECITEM(&derCRL, crl); + + object = nssToken_ImportCRL(token, NULL, + &derSubject, &derCRL, isKRL, url, PR_TRUE); + + if (object) { + rvH = object->handle; + nssCryptokiObject_Destroy(object); + } else { + rvH = CK_INVALID_HANDLE; + } + return rvH; +#endif +} /* @@ -3749,6 +3741,7 @@ PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, SECStatus SEC_DeletePermCRL(CERTSignedCrl *crl) { +#ifdef NSS_CLASSIC PK11SlotInfo *slot = crl->slot; CK_RV crv; @@ -3766,6 +3759,29 @@ SEC_DeletePermCRL(CERTSignedCrl *crl) crl->slot = NULL; PK11_FreeSlot(slot); return SECSuccess; +#else + PRStatus status; + NSSToken *token; + nssCryptokiObject *object; + PK11SlotInfo *slot = crl->slot; + + if (slot == NULL) { + /* shouldn't happen */ + PORT_SetError( SEC_ERROR_CRL_INVALID); + return SECFailure; + } + token = PK11Slot_GetNSSToken(slot); + + object = nss_ZNEW(NULL, nssCryptokiObject); + object->token = nssToken_AddRef(token); + object->handle = crl->pkcs11ID; + object->isTokenObject = PR_TRUE; + + status = nssToken_DeleteStoredObject(object); + + nssCryptokiObject_Destroy(object); + return (status == PR_SUCCESS) ? SECSuccess : SECFailure; +#endif } /* diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index edbbd9e4e..326ef8c99 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -727,10 +727,6 @@ PK11_Logout(PK11SlotInfo *slot) PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_Logout(slot->session); PK11_ExitSlotMonitor(slot); - if (slot->nssToken && !PK11_IsFriendly(slot)) { - /* If the slot certs are not public readable, destroy them */ - nssToken_DestroyCertList(slot->nssToken, PR_TRUE); - } if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; @@ -1146,11 +1142,6 @@ PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) } if (rv == SECSuccess) { rv = pk11_CheckVerifyTest(slot); - if (rv == SECSuccess && slot->nssToken && !PK11_IsFriendly(slot)) { - /* notify stan about the login if certs are not public readable */ - nssToken_LoadCerts(slot->nssToken); - nssToken_UpdateTrustForCerts(slot->nssToken); - } } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD); return rv; } diff --git a/security/nss/lib/pki/certificate.c b/security/nss/lib/pki/certificate.c index 049c8ddcb..a7041830a 100644 --- a/security/nss/lib/pki/certificate.c +++ b/security/nss/lib/pki/certificate.c @@ -1036,3 +1036,78 @@ nssSMIMEProfile_Destroy return PR_SUCCESS; } +NSS_IMPLEMENT NSSCRL * +nssCRL_Create +( + nssPKIObject *object +) +{ + PRStatus status; + NSSCRL *rvCRL; + NSSArena *arena = object->arena; + PR_ASSERT(object->instances != NULL && object->numInstances > 0); + rvCRL = nss_ZNEW(arena, NSSCRL); + if (!rvCRL) { + return (NSSCRL *)NULL; + } + rvCRL->object = *object; + /* XXX should choose instance based on some criteria */ + status = nssCryptokiCRL_GetAttributes(object->instances[0], + NULL, /* XXX sessionOpt */ + arena, + &rvCRL->encoding, + &rvCRL->url, + &rvCRL->isKRL); + if (status != PR_SUCCESS) { + return (NSSCRL *)NULL; + } + return rvCRL; +} + +NSS_IMPLEMENT NSSCRL * +nssCRL_AddRef +( + NSSCRL *crl +) +{ + if (crl) { + nssPKIObject_AddRef(&crl->object); + } + return crl; +} + +NSS_IMPLEMENT PRStatus +nssCRL_Destroy +( + NSSCRL *crl +) +{ + if (crl) { + (void)nssPKIObject_Destroy(&crl->object); + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssCRL_DeleteStoredObject +( + NSSCRL *crl, + NSSCallback *uhh +) +{ + return nssPKIObject_DeleteStoredObject(&crl->object, uhh, PR_TRUE); +} + +NSS_IMPLEMENT NSSDER * +nssCRL_GetEncoding +( + NSSCRL *crl +) +{ + if (crl->encoding.data != NULL && crl->encoding.size > 0) { + return &crl->encoding; + } else { + return (NSSDER *)NULL; + } +} + diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c index b9aa12ac5..fe770b179 100644 --- a/security/nss/lib/pki/pki3hack.c +++ b/security/nss/lib/pki/pki3hack.c @@ -71,9 +71,6 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "pkistore.h" #include "secmod.h" -/* if it's got more than 10 certs, it better handle traversal well */ -#define NSSTOKEN_MAX_LOCAL_CERTS 10 - NSSTrustDomain *g_default_trust_domain = NULL; NSSCryptoContext *g_default_crypto_context = NULL; @@ -100,232 +97,6 @@ STAN_GetDefaultCryptoToken return PK11Slot_GetNSSToken(pk11slot); } -static CERTCertificate * -stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate); - -/* stuff the cert in the global trust domain cache, and then add a reference - * to remain with the token in a list. - */ -static PRStatus -cache_token_cert(NSSCertificate *c, void *arg) -{ - NSSToken *token = (NSSToken *)arg; - NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - NSSCertificate *cp = nssCertificate_AddRef(c); - if (nssList_Count(token->certList) > NSSTOKEN_MAX_LOCAL_CERTS) { - nssToken_DestroyCertList(token, PR_TRUE); - /* terminate the traversal */ - return PR_FAILURE; - } - nssTrustDomain_AddCertsToCache(td, &c, 1); - if (cp == c) { - NSSCertificate_Destroy(cp); - } else { - /* The cert was already in the cache, from another token. Add this - * token's instance to the cert. - */ - nssCryptokiObject **instance; - instance = nssPKIObject_GetInstances(&cp->object); - nssPKIObject_AddInstance(&c->object, *instance); - nss_ZFreeIf(instance); - } - /* This list reference persists with the token */ - nssList_Add(token->certList, nssCertificate_AddRef(c)); - /* The cert needs to become external (made into a CERTCertificate) - * in order for it to be properly released. - * Force an update of the nickname and slot fields. - */ - (void)stan_GetCERTCertificate(c, PR_TRUE); - return PR_SUCCESS; -} - -static PRBool instance_destructor(NSSCertificate *c, NSSToken *token) -{ - nssPKIObject_RemoveInstanceForToken(&c->object, token); - /* XXX cheating, this code to be replaced anyway */ - if (c->object.numInstances == 0) { - return PR_TRUE; - } - return PR_FALSE; -} - -NSS_IMPLEMENT void -destroy_token_certs(nssList *certList, NSSToken *token, PRBool renewInstances) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRBool removeIt; - certs = nssList_CreateIterator(certList); - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - removeIt = instance_destructor(cert, token); - if (removeIt) { - nssList_Remove(certList, cert); - CERT_DestroyCertificate(STAN_GetCERTCertificate(cert)); - } else if (renewInstances) { - /* force an update of the nickname and slot fields of the cert */ - (void)stan_GetCERTCertificate(cert, PR_TRUE); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); -} - -NSS_IMPLEMENT void -nssCertificateList_DestroyTokenCerts(nssList *certList, NSSToken *token) -{ - destroy_token_certs(certList, token, PR_TRUE); -} - -NSS_IMPLEMENT void -nssCertificateList_RemoveTokenCerts(nssList *certList, NSSToken *token) -{ - nssListIterator *certs; - NSSCertificate *cert; - PRBool removeIt; - certs = nssList_CreateIterator(certList); - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - removeIt = instance_destructor(cert, token); - if (removeIt) { - nssList_Remove(certList, cert); - } else { - /* force an update of the nickname and slot fields of the cert */ - (void)stan_GetCERTCertificate(cert, PR_TRUE); - } - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); -} - -/* destroy the list of certs on a token */ -NSS_IMPLEMENT void -nssToken_DestroyCertList(NSSToken *token, PRBool renewInstances) -{ - if (!token->certList) { - return; - } - destroy_token_certs(token->certList, token, renewInstances); - nssList_Clear(token->certList, NULL); - /* leave the list non-null to prevent it from being searched */ -} - -static void -add_token_certs_to_list(NSSToken *token) -{ - nssCryptokiObject **objects, **op; - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - objects = nssToken_FindCertificates(token, NULL, tokenOnly, 0, NULL); - if (!objects) { - return; - } - for (op = objects; *op; op++) { - nssPKIObject *pkiob = nssPKIObject_Create(NULL, *op, - token->trustDomain, NULL); - if (pkiob) { - NSSCertificate *c = nssCertificate_Create(pkiob); - nssList_Add(token->certList, c); - } - } - nss_ZFreeIf(objects); -} - -/* create a list of local cert references for certain tokens */ -NSS_IMPLEMENT PRStatus -nssToken_LoadCerts(NSSToken *token) -{ - PRStatus nssrv = PR_SUCCESS; - nssTokenCertSearch search; - if (!PK11_IsInternal(token->pk11slot) && PK11_IsHW(token->pk11slot)) { - /* Hardware token certs will be immediately cached, and no searches - * will be performed on the token (the certs will be discovered by - * cache lookups) - */ - search.callback = cache_token_cert; - search.cbarg = token; - search.cached = NULL; - search.searchType = nssTokenSearchType_TokenOnly; - if (!token->certList) { - token->certList = nssList_Create(token->base.arena, PR_FALSE); - if (!token->certList) { - return PR_FAILURE; - } - } else if (nssList_Count(token->certList) > 0) { - /* already been done */ - return PR_SUCCESS; - } - /* ignore the rv, just work without the list */ - add_token_certs_to_list(token); - (void)nssToken_SetTrustCache(token); - (void)nssToken_SetCrlCache(token); - - /* even if there are no certs, leave a valid list pointer should - * any be imported. Having the pointer will also prevent searches, - * see below. - */ - if (nssList_Count(token->certList) == 0 && - !PK11_IsLoggedIn(token->pk11slot, NULL)) { - /* If the token is not logged in, that may be the reason no - * certs were found. - */ - token->loggedIn = PR_FALSE; - } - } - return nssrv; -} - -NSS_IMPLEMENT void -nssToken_UpdateTrustForCerts(NSSToken *token) -{ - nssListIterator *certs; - NSSCertificate *cert; - certs = nssList_CreateIterator(token->certList); - for (cert = (NSSCertificate *)nssListIterator_Start(certs); - cert != (NSSCertificate *)NULL; - cert = (NSSCertificate *)nssListIterator_Next(certs)) - { - CERTCertificate *cc = STAN_GetCERTCertificate(cert); - cc->trust = NULL; - /* force an update of the trust fields of the CERTCertificate */ - (void)stan_GetCERTCertificate(cert, PR_FALSE); - } - nssListIterator_Finish(certs); - nssListIterator_Destroy(certs); -} - -NSS_IMPLEMENT PRBool -nssToken_SearchCerts -( - NSSToken *token, - PRBool *notPresentOpt -) -{ - if (notPresentOpt) { - *notPresentOpt = PR_FALSE; - } - if (!nssToken_IsPresent(token)) { - nssToken_DestroyCertList(token, PR_TRUE); /* will free cached certs */ - if (notPresentOpt) { - *notPresentOpt = PR_TRUE; - } - } else if (token->certList && - nssList_Count(token->certList) == 0 && - !token->loggedIn) { - /* If the token has no cached certs, but wasn't logged in, check - * to see if it is logged in now and retry - */ - if (PK11_IsLoggedIn(token->pk11slot, NULL)) { - token->loggedIn = PR_TRUE; - nssToken_LoadCerts(token); - } - } - return (PRBool) (token->certList == NULL); -} - NSS_IMPLEMENT PRStatus STAN_LoadDefaultNSS3TrustDomain ( @@ -352,17 +123,9 @@ STAN_LoadDefaultNSS3TrustDomain } } SECMOD_ReleaseReadLock(moduleLock); + td->tokens = nssList_CreateIterator(td->tokenList); g_default_trust_domain = td; g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL); - /* Cache hardware token certs with the token to make them persistent */ - td->tokens = nssList_CreateIterator(td->tokenList); - for (token = (NSSToken *)nssListIterator_Start(td->tokens); - token != (NSSToken *)NULL; - token = (NSSToken *)nssListIterator_Next(td->tokens)) - { - nssToken_LoadCerts(token); - } - nssListIterator_Finish(td->tokens); return PR_SUCCESS; } @@ -379,7 +142,6 @@ STAN_AddModuleToDefaultTrustDomain for (i=0; i<module->slotCount; i++) { token = nssToken_CreateFromPK11SlotInfo(td, module->slots[i]); PK11Slot_SetNSSToken(module->slots[i], token); - nssToken_LoadCerts(token); nssList_Add(td->tokenList, token); } nssListIterator_Destroy(td->tokens); @@ -387,15 +149,6 @@ STAN_AddModuleToDefaultTrustDomain return SECSuccess; } -NSS_IMPLEMENT void -STAN_DestroyNSSToken(NSSToken *token) -{ - if (token->certList) { - nssToken_DestroyCertList(token, PR_FALSE); - } - nssToken_Destroy(token); -} - NSS_IMPLEMENT SECStatus STAN_RemoveModuleFromDefaultTrustDomain ( @@ -410,7 +163,7 @@ STAN_RemoveModuleFromDefaultTrustDomain token = PK11Slot_GetNSSToken(module->slots[i]); if (token) { nssList_Remove(td->tokenList, token); - STAN_DestroyNSSToken(token); + nssToken_Destroy(token); } } nssListIterator_Destroy(td->tokens); diff --git a/security/nss/lib/pki/pki3hack.h b/security/nss/lib/pki/pki3hack.h index 222dfdaf7..529c81e2b 100644 --- a/security/nss/lib/pki/pki3hack.h +++ b/security/nss/lib/pki/pki3hack.h @@ -75,29 +75,6 @@ STAN_LoadDefaultNSS3TrustDomain NSS_EXTERN void STAN_Shutdown(); -NSS_EXTERN void -STAN_DestroyNSSToken(NSSToken *token); - -NSS_EXTERN PRBool -nssToken_SearchCerts -( - NSSToken *token, - PRBool *notPresentOpt -); - -/* renewInstances -- if the cached token certs have multiple instances, - * don't destroy them. If this parameter is false, they will be destroyed - * anyway (used for clean shutdown). - */ -NSS_EXTERN void -nssToken_DestroyCertList(NSSToken *token, PRBool renewInstances); - -NSS_EXTERN void -nssCertificateList_DestroyTokenCerts(nssList *certList, NSSToken *token); - -NSS_EXTERN void -nssCertificateList_RemoveTokenCerts(nssList *certList, NSSToken *token); - NSS_EXTERN SECStatus STAN_AddModuleToDefaultTrustDomain ( diff --git a/security/nss/lib/pki/pkibase.c b/security/nss/lib/pki/pkibase.c index 3a20ae96f..75e3c77e0 100644 --- a/security/nss/lib/pki/pkibase.c +++ b/security/nss/lib/pki/pkibase.c @@ -506,6 +506,22 @@ nssCertificateArray_Traverse return status; } + +NSS_IMPLEMENT void +nssCRLArray_Destroy +( + NSSCRL **crls +) +{ + if (crls) { + NSSCRL **crlp; + for (crlp = crls; *crlp; crlp++) { + nssCRL_Destroy(*crlp); + } + nss_ZFreeIf(crls); + } +} + /* * Object collections */ @@ -513,8 +529,9 @@ nssCertificateArray_Traverse typedef enum { pkiObjectType_Certificate = 0, - pkiObjectType_PrivateKey = 1, - pkiObjectType_PublicKey = 2 + pkiObjectType_CRL = 1, + pkiObjectType_PrivateKey = 2, + pkiObjectType_PublicKey = 3 } pkiObjectType; /* Each object is defined by a set of items that uniquely identify it. @@ -847,6 +864,10 @@ nssPKIObjectCollection_Traverse status = (*callback->func.cert)((NSSCertificate *)node->object, callback->arg); break; + case pkiObjectType_CRL: + status = (*callback->func.crl)((NSSCRL *)node->object, + callback->arg); + break; case pkiObjectType_PrivateKey: status = (*callback->func.pvkey)((NSSPrivateKey *)node->object, callback->arg); @@ -989,6 +1010,109 @@ nssPKIObjectCollection_GetCertificates return rvOpt; } +/* + * CRL/KRL collections + */ + +static void +crl_destroyObject(nssPKIObject *o) +{ + NSSCRL *crl = (NSSCRL *)o; + nssCRL_Destroy(crl); +} + +static PRStatus +crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid) +{ + NSSCRL *crl = (NSSCRL *)o; + NSSDER *encoding; + encoding = nssCRL_GetEncoding(crl); + uid[0] = *encoding; + uid[1].data = NULL; uid[1].size = 0; + return PR_SUCCESS; +} + +static PRStatus +crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid, + NSSArena *arena) +{ + return nssCryptokiCRL_GetAttributes(instance, + NULL, /* XXX sessionOpt */ + arena, /* arena */ + &uid[0], /* encoding */ + NULL, /* url */ + NULL); /* isKRL */ +} + +static nssPKIObject * +crl_createObject(nssPKIObject *o) +{ + return (nssPKIObject *)nssCRL_Create(o); +} + +NSS_IMPLEMENT nssPKIObjectCollection * +nssCRLCollection_Create +( + NSSTrustDomain *td, + NSSCRL **crlsOpt +) +{ + PRStatus status; + nssPKIObjectCollection *collection; + collection = nssPKIObjectCollection_Create(td, NULL); + collection->objectType = pkiObjectType_CRL; + collection->destroyObject = crl_destroyObject; + collection->getUIDFromObject = crl_getUIDFromObject; + collection->getUIDFromInstance = crl_getUIDFromInstance; + collection->createObject = crl_createObject; + if (crlsOpt) { + for (; *crlsOpt; crlsOpt++) { + nssPKIObject *object = (nssPKIObject *)(*crlsOpt); + status = nssPKIObjectCollection_AddObject(collection, object); + } + } + return collection; +} + +NSS_IMPLEMENT NSSCRL ** +nssPKIObjectCollection_GetCRLs +( + nssPKIObjectCollection *collection, + NSSCRL **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +) +{ + PRStatus status; + PRUint32 rvSize; + PRBool allocated = PR_FALSE; + if (collection->size == 0) { + return (NSSCRL **)NULL; + } + if (maximumOpt == 0) { + rvSize = collection->size; + } else { + rvSize = PR_MIN(collection->size, maximumOpt); + } + if (!rvOpt) { + rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1); + if (!rvOpt) { + return (NSSCRL **)NULL; + } + allocated = PR_TRUE; + } + status = nssPKIObjectCollection_GetObjects(collection, + (nssPKIObject **)rvOpt, + rvSize); + if (status != PR_SUCCESS) { + if (allocated) { + nss_ZFreeIf(rvOpt); + } + return (NSSCRL **)NULL; + } + return rvOpt; +} + #ifdef PURE_STAN_BUILD /* * PrivateKey collections diff --git a/security/nss/lib/pki/pkim.h b/security/nss/lib/pki/pkim.h index d928d24e5..16ac87f3c 100644 --- a/security/nss/lib/pki/pkim.h +++ b/security/nss/lib/pki/pkim.h @@ -194,6 +194,13 @@ nssTrustDomain_FindCertificatesByID NSSArena *arenaOpt ); +NSS_EXTERN NSSCRL ** +nssTrustDomain_FindCRLsBySubject +( + NSSTrustDomain *td, + NSSDER *subject +); + /* module-private nsspki methods */ NSS_EXTERN NSSCryptoContext * @@ -243,12 +250,43 @@ nssTrust_Create nssPKIObject *object ); +NSS_EXTERN NSSCRL * +nssCRL_Create +( + nssPKIObject *object +); + +NSS_EXTERN NSSCRL * +nssCRL_AddRef +( + NSSCRL *crl +); + +NSS_EXTERN PRStatus +nssCRL_Destroy +( + NSSCRL *crl +); + +NSS_EXTERN PRStatus +nssCRL_DeleteStoredObject +( + NSSCRL *crl, + NSSCallback *uhh +); + NSS_EXTERN NSSPrivateKey * nssPrivateKey_Create ( nssPKIObject *o ); +NSS_EXTERN NSSDER * +nssCRL_GetEncoding +( + NSSCRL *crl +); + NSS_EXTERN NSSPublicKey * nssPublicKey_Create ( @@ -320,6 +358,12 @@ nssCertificateArray_Traverse void *arg ); +NSS_EXTERN void +nssCRLArray_Destroy +( + NSSCRL **crls +); + /* nssPKIObjectCollection * * This is a handy way to group objects together and perform operations @@ -348,6 +392,7 @@ nssCertificateArray_Traverse * Back to type-specific methods. * * nssPKIObjectCollection_GetCertificates + * nssPKIObjectCollection_GetCRLs * nssPKIObjectCollection_GetPrivateKeys * nssPKIObjectCollection_GetPublicKeys */ @@ -364,6 +409,18 @@ nssCertificateCollection_Create NSSCertificate **certsOpt ); +/* nssCRLCollection_Create + * + * Create a collection of CRLs/KRLs in the specified trust domain. + * Optionally provide a starting set of CRLs. + */ +NSS_EXTERN nssPKIObjectCollection * +nssCRLCollection_Create +( + NSSTrustDomain *td, + NSSCRL **crlsOpt +); + /* nssPrivateKeyCollection_Create * * Create a collection of private keys in the specified trust domain. @@ -452,6 +509,15 @@ nssPKIObjectCollection_GetCertificates NSSArena *arenaOpt ); +NSS_EXTERN NSSCRL ** +nssPKIObjectCollection_GetCRLs +( + nssPKIObjectCollection *collection, + NSSCRL **rvOpt, + PRUint32 maximumOpt, + NSSArena *arenaOpt +); + NSS_EXTERN NSSPrivateKey ** nssPKIObjectCollection_GetPrivateKeys ( diff --git a/security/nss/lib/pki/pkit.h b/security/nss/lib/pki/pkit.h index 23008d352..f8bd067b9 100644 --- a/security/nss/lib/pki/pkit.h +++ b/security/nss/lib/pki/pkit.h @@ -190,6 +190,15 @@ struct NSSTimeStr { PRTime prTime; }; +struct NSSCRLStr { + nssPKIObject object; + NSSDER encoding; + NSSUTF8 *url; + PRBool isKRL; +}; + +typedef struct NSSCRLStr NSSCRL; + struct NSSPoliciesStr; struct NSSAlgorithmAndParametersStr; diff --git a/security/nss/lib/pki/pkitm.h b/security/nss/lib/pki/pkitm.h index 699a1b91c..d163923e6 100644 --- a/security/nss/lib/pki/pkitm.h +++ b/security/nss/lib/pki/pkitm.h @@ -110,6 +110,7 @@ typedef struct { union { PRStatus (* cert)(NSSCertificate *c, void *arg); + PRStatus (* crl)(NSSCRL *crl, void *arg); PRStatus (* pvkey)(NSSPrivateKey *vk, void *arg); PRStatus (* pbkey)(NSSPublicKey *bk, void *arg); } func; diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c index 2fc2dedfc..1f3488186 100644 --- a/security/nss/lib/pki/trustdomain.c +++ b/security/nss/lib/pki/trustdomain.c @@ -109,7 +109,7 @@ token_destructor(void *t) NSSToken *tok = (NSSToken *)t; /* in 3.4, also destroy the slot (managed separately) */ (void)nssSlot_Destroy(tok->slot); - STAN_DestroyNSSToken(tok); + nssToken_Destroy(tok); } NSS_IMPLEMENT PRStatus @@ -1136,25 +1136,27 @@ nssTrustDomain_FindTrustForCertificate } for (slotp = slots; *slotp; slotp++) { token = nssSlot_GetToken(*slotp); - to = nssToken_FindTrustForCertificate(token, NULL, - &c->encoding, - &c->issuer, - &c->serial, + if (token) { + to = nssToken_FindTrustForCertificate(token, NULL, + &c->encoding, + &c->issuer, + &c->serial, nssTokenSearchType_TokenOnly); - if (to) { - if (!pkio) { - pkio = nssPKIObject_Create(NULL, to, td, NULL); + if (to) { if (!pkio) { - goto loser; - } - } else { - status = nssPKIObject_AddInstance(pkio, to); - if (status != PR_SUCCESS) { - goto loser; + pkio = nssPKIObject_Create(NULL, to, td, NULL); + if (!pkio) { + goto loser; + } + } else { + status = nssPKIObject_AddInstance(pkio, to); + if (status != PR_SUCCESS) { + goto loser; + } } } + nssToken_Destroy(token); } - nssToken_Destroy(token); } if (pkio) { rvt = nssTrust_Create(pkio); @@ -1175,6 +1177,66 @@ loser: return (NSSTrust *)NULL; } +NSS_IMPLEMENT NSSCRL ** +nssTrustDomain_FindCRLsBySubject +( + NSSTrustDomain *td, + NSSDER *subject +) +{ + PRStatus status; + NSSSlot **slots; + NSSSlot **slotp; + NSSToken *token; + nssUpdateLevel updateLevel; + nssPKIObjectCollection *collection; + NSSCRL **rvCRLs = NULL; + collection = nssCRLCollection_Create(td, NULL); + if (!collection) { + return (NSSCRL **)NULL; + } + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + for (slotp = slots; *slotp; slotp++) { + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssCryptokiObject **instances; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + /* get a session for the token */ + session = nssTrustDomain_GetSessionForToken(td, token); + if (!session) { + nssToken_Destroy(token); + goto loser; + } + /* perform the traversal */ + instances = nssToken_FindCRLsBySubject(token, session, subject, + tokenOnly, 0, &status); + nssToken_Destroy(token); + if (status != PR_SUCCESS) { + goto loser; + } + /* add the found CRL's to the collection */ + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + nss_ZFreeIf(instances); + if (status != PR_SUCCESS) { + goto loser; + } + } + } + rvCRLs = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL); + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return rvCRLs; +loser: + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return (NSSCRL **)NULL; +} + NSS_IMPLEMENT PRStatus NSSTrustDomain_GenerateKeyPair ( |