diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /security/nss/lib/pki/trustdomain.c | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | security/nss/lib/pki/trustdomain.c | 1230 |
1 files changed, 1230 insertions, 0 deletions
diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c new file mode 100644 index 0000000000..fc3b0f0da8 --- /dev/null +++ b/security/nss/lib/pki/trustdomain.c @@ -0,0 +1,1230 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DEV_H +#include "dev.h" +#endif /* DEV_H */ + +#ifndef PKIM_H +#include "pkim.h" +#endif /* PKIM_H */ + +#include "cert.h" +#include "dev3hack.h" +#include "pki3hack.h" +#include "pk11pub.h" +#include "nssrwlk.h" +#include "pk11priv.h" + +#define NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE 32 + +extern const NSSError NSS_ERROR_NOT_FOUND; + +typedef PRUint32 nssUpdateLevel; + +NSS_IMPLEMENT NSSTrustDomain * +NSSTrustDomain_Create( + NSSUTF8 *moduleOpt, + NSSUTF8 *uriOpt, + NSSUTF8 *opaqueOpt, + void *reserved) +{ + NSSArena *arena; + NSSTrustDomain *rvTD; + arena = NSSArena_Create(); + if (!arena) { + return (NSSTrustDomain *)NULL; + } + rvTD = nss_ZNEW(arena, NSSTrustDomain); + if (!rvTD) { + goto loser; + } + /* protect the token list and the token iterator */ + rvTD->tokensLock = NSSRWLock_New(100, "tokens"); + if (!rvTD->tokensLock) { + goto loser; + } + nssTrustDomain_InitializeCache(rvTD, NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE); + rvTD->arena = arena; + rvTD->refCount = 1; + rvTD->statusConfig = NULL; + return rvTD; +loser: + if (rvTD && rvTD->tokensLock) { + NSSRWLock_Destroy(rvTD->tokensLock); + } + nssArena_Destroy(arena); + return (NSSTrustDomain *)NULL; +} + +static void +token_destructor(void *t) +{ + NSSToken *tok = (NSSToken *)t; + /* Remove the token list's reference to the token */ + (void)nssToken_Destroy(tok); + + /* Signal that the slot should not give out any more references to the + * token. The token might still have a positive refcount after this call. + * The token has a reference to the slot, so the slot will not be destroyed + * until after the token's refcount drops to 0. */ + PK11Slot_SetNSSToken(tok->pk11slot, NULL); +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_Destroy( + NSSTrustDomain *td) +{ + PRStatus status = PR_SUCCESS; + if (--td->refCount == 0) { + /* Destroy each token in the list of tokens */ + if (td->tokens) { + nssListIterator_Destroy(td->tokens); + td->tokens = NULL; + } + if (td->tokenList) { + nssList_Clear(td->tokenList, token_destructor); + nssList_Destroy(td->tokenList); + td->tokenList = NULL; + } + NSSRWLock_Destroy(td->tokensLock); + td->tokensLock = NULL; + status = nssTrustDomain_DestroyCache(td); + if (status == PR_FAILURE) { + return status; + } + if (td->statusConfig) { + td->statusConfig->statusDestroy(td->statusConfig); + td->statusConfig = NULL; + } + /* Destroy the trust domain */ + nssArena_Destroy(td->arena); + } + return status; +} + +/* XXX uses tokens until slot list is in place */ +static NSSSlot ** +nssTrustDomain_GetActiveSlots( + NSSTrustDomain *td, + nssUpdateLevel *updateLevel) +{ + PRUint32 count; + NSSSlot **slots = NULL; + NSSToken **tp, **tokens; + *updateLevel = 1; + if (!td->tokenList) { + return NULL; + } + NSSRWLock_LockRead(td->tokensLock); + count = nssList_Count(td->tokenList); + tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1); + if (!tokens) { + NSSRWLock_UnlockRead(td->tokensLock); + return NULL; + } + slots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1); + if (!slots) { + NSSRWLock_UnlockRead(td->tokensLock); + nss_ZFreeIf(tokens); + return NULL; + } + nssList_GetArray(td->tokenList, (void **)tokens, count); + count = 0; + for (tp = tokens; *tp; tp++) { + NSSSlot *slot = nssToken_GetSlot(*tp); + if (!PK11_IsDisabled(slot->pk11slot)) { + slots[count++] = slot; + } else { + nssSlot_Destroy(slot); + } + } + NSSRWLock_UnlockRead(td->tokensLock); + nss_ZFreeIf(tokens); + if (!count) { + nss_ZFreeIf(slots); + slots = NULL; + } + return slots; +} + +/* XXX */ +static nssSession * +nssTrustDomain_GetSessionForToken( + NSSTrustDomain *td, + NSSToken *token) +{ + return nssToken_GetDefaultSession(token); +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_SetDefaultCallback( + NSSTrustDomain *td, + NSSCallback *newCallback, + NSSCallback **oldCallbackOpt) +{ + if (oldCallbackOpt) { + *oldCallbackOpt = td->defaultCallback; + } + td->defaultCallback = newCallback; + return PR_SUCCESS; +} + +NSS_IMPLEMENT NSSCallback * +nssTrustDomain_GetDefaultCallback( + NSSTrustDomain *td, + PRStatus *statusOpt) +{ + if (statusOpt) { + *statusOpt = PR_SUCCESS; + } + return td->defaultCallback; +} + +NSS_IMPLEMENT NSSCallback * +NSSTrustDomain_GetDefaultCallback( + NSSTrustDomain *td, + PRStatus *statusOpt) +{ + return nssTrustDomain_GetDefaultCallback(td, statusOpt); +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_LoadModule( + NSSTrustDomain *td, + NSSUTF8 *moduleOpt, + NSSUTF8 *uriOpt, + NSSUTF8 *opaqueOpt, + void *reserved) +{ + return PR_FAILURE; +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_DisableToken( + NSSTrustDomain *td, + NSSToken *token, + NSSError why) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return PR_FAILURE; +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_EnableToken( + NSSTrustDomain *td, + NSSToken *token) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return PR_FAILURE; +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_IsTokenEnabled( + NSSTrustDomain *td, + NSSToken *token, + NSSError *whyOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return PR_FAILURE; +} + +NSS_IMPLEMENT NSSSlot * +NSSTrustDomain_FindSlotByName( + NSSTrustDomain *td, + NSSUTF8 *slotName) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSToken ** +NSSTrustDomain_FindTokensByURI( + NSSTrustDomain *td, + PK11URI *uri) +{ + NSSToken *tok = NULL; + PK11SlotInfo *slotinfo; + NSSToken **tokens; + int count, i = 0; + + NSSRWLock_LockRead(td->tokensLock); + count = nssList_Count(td->tokenList); + tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1); + if (!tokens) { + return NULL; + } + for (tok = (NSSToken *)nssListIterator_Start(td->tokens); + tok != (NSSToken *)NULL; + tok = (NSSToken *)nssListIterator_Next(td->tokens)) { + if (nssToken_IsPresent(tok)) { + slotinfo = tok->pk11slot; + if (pk11_MatchUriTokenInfo(slotinfo, uri)) + tokens[i++] = nssToken_AddRef(tok); + } + } + tokens[i] = NULL; + nssListIterator_Finish(td->tokens); + NSSRWLock_UnlockRead(td->tokensLock); + return tokens; +} + +NSS_IMPLEMENT NSSToken * +NSSTrustDomain_FindTokenByName( + NSSTrustDomain *td, + NSSUTF8 *tokenName) +{ + PRStatus nssrv; + NSSUTF8 *myName; + NSSToken *tok = NULL; + NSSRWLock_LockRead(td->tokensLock); + for (tok = (NSSToken *)nssListIterator_Start(td->tokens); + tok != (NSSToken *)NULL; + tok = (NSSToken *)nssListIterator_Next(td->tokens)) { + if (nssToken_IsPresent(tok)) { + myName = nssToken_GetName(tok); + if (nssUTF8_Equal(tokenName, myName, &nssrv)) { + tok = nssToken_AddRef(tok); + break; + } + } + } + nssListIterator_Finish(td->tokens); + NSSRWLock_UnlockRead(td->tokensLock); + return tok; +} + +NSS_IMPLEMENT NSSToken * +NSSTrustDomain_FindTokenBySlotName( + NSSTrustDomain *td, + NSSUTF8 *slotName) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSToken * +NSSTrustDomain_FindTokenForAlgorithm( + NSSTrustDomain *td, + NSSOID *algorithm) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSToken * +NSSTrustDomain_FindBestTokenForAlgorithms( + NSSTrustDomain *td, + NSSOID *algorithms[], /* may be null-terminated */ + PRUint32 nAlgorithmsOpt /* limits the array if nonzero */ +) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_Login( + NSSTrustDomain *td, + NSSCallback *uhhOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return PR_FAILURE; +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_Logout(NSSTrustDomain *td) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return PR_FAILURE; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_ImportCertificate( + NSSTrustDomain *td, + NSSCertificate *c) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_ImportPKIXCertificate( + NSSTrustDomain *td, + /* declared as a struct until these "data types" are defined */ + struct NSSPKIXCertificateStr *pc) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_ImportEncodedCertificate( + NSSTrustDomain *td, + NSSBER *ber) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_ImportEncodedCertificateChain( + NSSTrustDomain *td, + NSSBER *ber, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSPrivateKey * +NSSTrustDomain_ImportEncodedPrivateKey( + NSSTrustDomain *td, + NSSBER *ber, + NSSItem *passwordOpt, /* NULL will cause a callback */ + NSSCallback *uhhOpt, + NSSToken *destination) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSPublicKey * +NSSTrustDomain_ImportEncodedPublicKey( + NSSTrustDomain *td, + NSSBER *ber) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +static NSSCertificate ** +get_certs_from_list(nssList *list) +{ + PRUint32 count = nssList_Count(list); + NSSCertificate **certs = NULL; + if (count > 0) { + certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); + if (certs) { + nssList_GetArray(list, (void **)certs, count); + } + } + return certs; +} + +NSS_IMPLEMENT NSSCertificate ** +nssTrustDomain_FindCertificatesByNickname( + NSSTrustDomain *td, + const NSSUTF8 *name, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt) +{ + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; + NSSCertificate **rvCerts = NULL; + nssPKIObjectCollection *collection = NULL; + nssUpdateLevel updateLevel; + nssList *nameList; + PRUint32 numRemaining = maximumOpt; + PRUint32 collectionCount = 0; + PRUint32 errors = 0; + + /* First, grab from the cache */ + nameList = nssList_Create(NULL, PR_FALSE); + if (!nameList) { + return NULL; + } + (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList); + rvCerts = get_certs_from_list(nameList); + /* initialize the collection of token certificates with the set of + * cached certs (if any). + */ + collection = nssCertificateCollection_Create(td, rvCerts); + nssCertificateArray_Destroy(rvCerts); + nssList_Destroy(nameList); + if (!collection) { + return (NSSCertificate **)NULL; + } + /* obtain the current set of active slots in the trust domain */ + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + /* iterate over the slots */ + for (slotp = slots; *slotp; slotp++) { + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssCryptokiObject **instances = NULL; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + PRStatus status = PR_FAILURE; + + session = nssTrustDomain_GetSessionForToken(td, token); + if (session) { + instances = nssToken_FindCertificatesByNickname(token, + session, + name, + tokenOnly, + numRemaining, + &status); + } + (void)nssToken_Destroy(token); + if (status != PR_SUCCESS) { + errors++; + continue; + } + if (instances) { + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + nss_ZFreeIf(instances); + if (status != PR_SUCCESS) { + errors++; + continue; + } + collectionCount = nssPKIObjectCollection_Count(collection); + if (maximumOpt > 0) { + if (collectionCount >= maximumOpt) + break; + numRemaining = maximumOpt - collectionCount; + } + } + } + } + if (!collectionCount && errors) + goto loser; + /* Grab the certs collected in the search. */ + rvCerts = nssPKIObjectCollection_GetCertificates(collection, + rvOpt, maximumOpt, + arenaOpt); + /* clean up */ + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return rvCerts; +loser: + if (slots) { + nssSlotArray_Destroy(slots); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + return (NSSCertificate **)NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindCertificatesByNickname( + NSSTrustDomain *td, + NSSUTF8 *name, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt) +{ + return nssTrustDomain_FindCertificatesByNickname(td, + name, + rvOpt, + maximumOpt, + arenaOpt); +} + +NSS_IMPLEMENT NSSCertificate * +nssTrustDomain_FindBestCertificateByNickname( + NSSTrustDomain *td, + const NSSUTF8 *name, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt) +{ + NSSCertificate **nicknameCerts; + NSSCertificate *rvCert = NULL; + nicknameCerts = nssTrustDomain_FindCertificatesByNickname(td, name, + NULL, + 0, + NULL); + if (nicknameCerts) { + rvCert = nssCertificateArray_FindBestCertificate(nicknameCerts, + timeOpt, + usage, + policiesOpt); + nssCertificateArray_Destroy(nicknameCerts); + } + return rvCert; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestCertificateByNickname( + NSSTrustDomain *td, + const NSSUTF8 *name, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt) +{ + return nssTrustDomain_FindBestCertificateByNickname(td, + name, + timeOpt, + usage, + policiesOpt); +} + +NSS_IMPLEMENT NSSCertificate ** +nssTrustDomain_FindCertificatesBySubject( + NSSTrustDomain *td, + NSSDER *subject, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt) +{ + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; + NSSCertificate **rvCerts = NULL; + nssPKIObjectCollection *collection = NULL; + nssUpdateLevel updateLevel; + nssList *subjectList; + PRUint32 numRemaining = maximumOpt; + PRUint32 collectionCount = 0; + PRUint32 errors = 0; + + /* look in cache */ + subjectList = nssList_Create(NULL, PR_FALSE); + if (!subjectList) { + return NULL; + } + (void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList); + rvCerts = get_certs_from_list(subjectList); + collection = nssCertificateCollection_Create(td, rvCerts); + nssCertificateArray_Destroy(rvCerts); + nssList_Destroy(subjectList); + if (!collection) { + return (NSSCertificate **)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 = NULL; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + PRStatus status = PR_FAILURE; + + session = nssTrustDomain_GetSessionForToken(td, token); + if (session) { + instances = nssToken_FindCertificatesBySubject(token, + session, + subject, + tokenOnly, + numRemaining, + &status); + } + (void)nssToken_Destroy(token); + if (status != PR_SUCCESS) { + errors++; + continue; + } + if (instances) { + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + nss_ZFreeIf(instances); + if (status != PR_SUCCESS) { + errors++; + continue; + } + collectionCount = nssPKIObjectCollection_Count(collection); + if (maximumOpt > 0) { + if (collectionCount >= maximumOpt) + break; + numRemaining = maximumOpt - collectionCount; + } + } + } + } + if (!collectionCount && errors) + goto loser; + rvCerts = nssPKIObjectCollection_GetCertificates(collection, + rvOpt, maximumOpt, + arenaOpt); + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return rvCerts; +loser: + if (slots) { + nssSlotArray_Destroy(slots); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + return (NSSCertificate **)NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindCertificatesBySubject( + NSSTrustDomain *td, + NSSDER *subject, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, + NSSArena *arenaOpt) +{ + return nssTrustDomain_FindCertificatesBySubject(td, + subject, + rvOpt, + maximumOpt, + arenaOpt); +} + +NSS_IMPLEMENT NSSCertificate * +nssTrustDomain_FindBestCertificateBySubject( + NSSTrustDomain *td, + NSSDER *subject, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt) +{ + NSSCertificate **subjectCerts; + NSSCertificate *rvCert = NULL; + subjectCerts = nssTrustDomain_FindCertificatesBySubject(td, subject, + NULL, + 0, + NULL); + if (subjectCerts) { + rvCert = nssCertificateArray_FindBestCertificate(subjectCerts, + timeOpt, + usage, + policiesOpt); + nssCertificateArray_Destroy(subjectCerts); + } + return rvCert; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestCertificateBySubject( + NSSTrustDomain *td, + NSSDER *subject, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt) +{ + return nssTrustDomain_FindBestCertificateBySubject(td, + subject, + timeOpt, + usage, + policiesOpt); +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestCertificateByNameComponents( + NSSTrustDomain *td, + NSSUTF8 *nameComponents, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindCertificatesByNameComponents( + NSSTrustDomain *td, + NSSUTF8 *nameComponents, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +/* This returns at most a single certificate, so it can stop the loop + * when one is found. + */ +NSS_IMPLEMENT NSSCertificate * +nssTrustDomain_FindCertificateByIssuerAndSerialNumber( + NSSTrustDomain *td, + NSSDER *issuer, + NSSDER *serial) +{ + NSSSlot **slots = NULL; + NSSSlot **slotp; + NSSCertificate *rvCert = NULL; + nssPKIObjectCollection *collection = NULL; + nssUpdateLevel updateLevel; + + /* see if this search is already cached */ + rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td, + issuer, + serial); + if (rvCert) { + return rvCert; + } + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (slots) { + for (slotp = slots; *slotp; slotp++) { + NSSToken *token = nssSlot_GetToken(*slotp); + nssSession *session; + nssCryptokiObject *instance; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + PRStatus status = PR_FAILURE; + + if (!token) + continue; + session = nssTrustDomain_GetSessionForToken(td, token); + if (session) { + instance = nssToken_FindCertificateByIssuerAndSerialNumber( + token, + session, + issuer, + serial, + tokenOnly, + &status); + } + (void)nssToken_Destroy(token); + if (status != PR_SUCCESS) { + continue; + } + if (instance) { + if (!collection) { + collection = nssCertificateCollection_Create(td, NULL); + if (!collection) { + break; /* don't keep looping if out if memory */ + } + } + status = nssPKIObjectCollection_AddInstances(collection, + &instance, 1); + if (status == PR_SUCCESS) { + (void)nssPKIObjectCollection_GetCertificates( + collection, &rvCert, 1, NULL); + } + if (rvCert) { + break; /* found one cert, all done */ + } + } + } + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + if (slots) { + nssSlotArray_Destroy(slots); + } + return rvCert; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindCertificateByIssuerAndSerialNumber( + NSSTrustDomain *td, + NSSDER *issuer, + NSSDER *serial) +{ + return nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td, + issuer, + serial); +} + +NSS_IMPLEMENT NSSCertificate * +nssTrustDomain_FindCertificateByEncodedCertificate( + NSSTrustDomain *td, + NSSBER *ber) +{ + PRStatus status; + NSSCertificate *rvCert = NULL; + NSSDER issuer = { 0 }; + NSSDER serial = { 0 }; + /* XXX this is not generic... will any cert crack into issuer/serial? */ + status = nssPKIX509_GetIssuerAndSerialFromDER(ber, &issuer, &serial); + if (status != PR_SUCCESS) { + return NULL; + } + rvCert = nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td, + &issuer, + &serial); + PORT_Free(issuer.data); + PORT_Free(serial.data); + return rvCert; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindCertificateByEncodedCertificate( + NSSTrustDomain *td, + NSSBER *ber) +{ + return nssTrustDomain_FindCertificateByEncodedCertificate(td, ber); +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestCertificateByEmail( + NSSTrustDomain *td, + NSSASCII7 *email, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt) +{ + return 0; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindCertificatesByEmail( + NSSTrustDomain *td, + NSSASCII7 *email, + NSSCertificate *rvOpt[], + PRUint32 maximumOpt, /* 0 for no max */ + NSSArena *arenaOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindCertificateByOCSPHash( + NSSTrustDomain *td, + NSSItem *hash) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestUserCertificate( + NSSTrustDomain *td, + NSSTime *timeOpt, + NSSUsage *usage, + NSSPolicies *policiesOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindUserCertificates( + NSSTrustDomain *td, + NSSTime *timeOpt, + NSSUsage *usageOpt, + NSSPolicies *policiesOpt, + NSSCertificate **rvOpt, + PRUint32 rvLimit, /* zero for no limit */ + NSSArena *arenaOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestUserCertificateForSSLClientAuth( + NSSTrustDomain *td, + NSSUTF8 *sslHostOpt, + NSSDER *rootCAsOpt[], /* null pointer for none */ + PRUint32 rootCAsMaxOpt, /* zero means list is null-terminated */ + NSSAlgorithmAndParameters *apOpt, + NSSPolicies *policiesOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindUserCertificatesForSSLClientAuth( + NSSTrustDomain *td, + NSSUTF8 *sslHostOpt, + NSSDER *rootCAsOpt[], /* null pointer for none */ + PRUint32 rootCAsMaxOpt, /* zero means list is null-terminated */ + NSSAlgorithmAndParameters *apOpt, + NSSPolicies *policiesOpt, + NSSCertificate **rvOpt, + PRUint32 rvLimit, /* zero for no limit */ + NSSArena *arenaOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate * +NSSTrustDomain_FindBestUserCertificateForEmailSigning( + NSSTrustDomain *td, + NSSASCII7 *signerOpt, + NSSASCII7 *recipientOpt, + /* anything more here? */ + NSSAlgorithmAndParameters *apOpt, + NSSPolicies *policiesOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSTrustDomain_FindUserCertificatesForEmailSigning( + NSSTrustDomain *td, + NSSASCII7 *signerOpt, + NSSASCII7 *recipientOpt, + /* anything more here? */ + NSSAlgorithmAndParameters *apOpt, + NSSPolicies *policiesOpt, + NSSCertificate **rvOpt, + PRUint32 rvLimit, /* zero for no limit */ + NSSArena *arenaOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +static PRStatus +collector(nssCryptokiObject *instance, void *arg) +{ + nssPKIObjectCollection *collection = (nssPKIObjectCollection *)arg; + return nssPKIObjectCollection_AddInstanceAsObject(collection, instance); +} + +NSS_IMPLEMENT PRStatus * +NSSTrustDomain_TraverseCertificates( + NSSTrustDomain *td, + PRStatus (*callback)(NSSCertificate *c, void *arg), + void *arg) +{ + NSSToken *token = NULL; + NSSSlot **slots = NULL; + NSSSlot **slotp; + nssPKIObjectCollection *collection = NULL; + nssPKIObjectCallback pkiCallback; + nssUpdateLevel updateLevel; + NSSCertificate **cached = NULL; + nssList *certList; + + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) + return NULL; + (void)nssTrustDomain_GetCertsFromCache(td, certList); + cached = get_certs_from_list(certList); + collection = nssCertificateCollection_Create(td, cached); + nssCertificateArray_Destroy(cached); + nssList_Destroy(certList); + if (!collection) { + return (PRStatus *)NULL; + } + /* obtain the current set of active slots in the trust domain */ + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + goto loser; + } + /* iterate over the slots */ + for (slotp = slots; *slotp; slotp++) { + /* get the token for the slot, if present */ + token = nssSlot_GetToken(*slotp); + if (token) { + nssSession *session; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + /* get a session for the token */ + session = nssTrustDomain_GetSessionForToken(td, token); + if (session) { + /* perform the traversal */ + (void)nssToken_TraverseCertificates(token, + session, + tokenOnly, + collector, + collection); + } + (void)nssToken_Destroy(token); + } + } + + /* Traverse the collection */ + pkiCallback.func.cert = callback; + pkiCallback.arg = arg; + (void)nssPKIObjectCollection_Traverse(collection, &pkiCallback); +loser: + if (slots) { + nssSlotArray_Destroy(slots); + } + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + return NULL; +} + +NSS_IMPLEMENT NSSTrust * +nssTrustDomain_FindTrustForCertificate( + NSSTrustDomain *td, + NSSCertificate *c) +{ + NSSSlot **slots; + NSSSlot **slotp; + nssCryptokiObject *to = NULL; + nssPKIObject *pkio = NULL; + NSSTrust *rvt = NULL; + nssUpdateLevel updateLevel; + slots = nssTrustDomain_GetActiveSlots(td, &updateLevel); + if (!slots) { + return (NSSTrust *)NULL; + } + for (slotp = slots; *slotp; slotp++) { + NSSToken *token = nssSlot_GetToken(*slotp); + + if (token) { + to = nssToken_FindTrustForCertificate(token, NULL, + &c->encoding, + &c->issuer, + &c->serial, + nssTokenSearchType_TokenOnly); + if (to) { + PRStatus status; + if (!pkio) { + pkio = nssPKIObject_Create(NULL, to, td, NULL, nssPKILock); + status = pkio ? PR_SUCCESS : PR_FAILURE; + } else { + status = nssPKIObject_AddInstance(pkio, to); + } + if (status != PR_SUCCESS) { + nssCryptokiObject_Destroy(to); + } + } + (void)nssToken_Destroy(token); + } + } + if (pkio) { + rvt = nssTrust_Create(pkio, &c->encoding); + if (rvt) { + pkio = NULL; /* rvt object now owns the pkio reference */ + } + } + nssSlotArray_Destroy(slots); + if (pkio) { + nssPKIObject_Destroy(pkio); + } + return rvt; +} + +NSS_IMPLEMENT NSSCRL ** +nssTrustDomain_FindCRLsBySubject( + NSSTrustDomain *td, + NSSDER *subject) +{ + 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) { + PRStatus status = PR_FAILURE; + nssSession *session; + nssCryptokiObject **instances = NULL; + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; + + /* get a session for the token */ + session = nssTrustDomain_GetSessionForToken(td, token); + if (session) { + /* perform the traversal */ + instances = nssToken_FindCRLsBySubject(token, session, subject, + tokenOnly, 0, &status); + } + (void)nssToken_Destroy(token); + if (status == PR_SUCCESS) { + /* add the found CRL's to the collection */ + status = nssPKIObjectCollection_AddInstances(collection, + instances, 0); + } + nss_ZFreeIf(instances); + } + } + rvCRLs = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL); +loser: + nssPKIObjectCollection_Destroy(collection); + nssSlotArray_Destroy(slots); + return rvCRLs; +} + +NSS_IMPLEMENT PRStatus +NSSTrustDomain_GenerateKeyPair( + NSSTrustDomain *td, + NSSAlgorithmAndParameters *ap, + NSSPrivateKey **pvkOpt, + NSSPublicKey **pbkOpt, + PRBool privateKeyIsSensitive, + NSSToken *destination, + NSSCallback *uhhOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return PR_FAILURE; +} + +NSS_IMPLEMENT NSSSymmetricKey * +NSSTrustDomain_GenerateSymmetricKey( + NSSTrustDomain *td, + NSSAlgorithmAndParameters *ap, + PRUint32 keysize, + NSSToken *destination, + NSSCallback *uhhOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSSymmetricKey * +NSSTrustDomain_GenerateSymmetricKeyFromPassword( + NSSTrustDomain *td, + NSSAlgorithmAndParameters *ap, + NSSUTF8 *passwordOpt, /* if null, prompt */ + NSSToken *destinationOpt, + NSSCallback *uhhOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSSymmetricKey * +NSSTrustDomain_FindSymmetricKeyByAlgorithmAndKeyID( + NSSTrustDomain *td, + NSSOID *algorithm, + NSSItem *keyID, + NSSCallback *uhhOpt) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCryptoContext * +nssTrustDomain_CreateCryptoContext( + NSSTrustDomain *td, + NSSCallback *uhhOpt) +{ + return nssCryptoContext_Create(td, uhhOpt); +} + +NSS_IMPLEMENT NSSCryptoContext * +NSSTrustDomain_CreateCryptoContext( + NSSTrustDomain *td, + NSSCallback *uhhOpt) +{ + return nssTrustDomain_CreateCryptoContext(td, uhhOpt); +} + +NSS_IMPLEMENT NSSCryptoContext * +NSSTrustDomain_CreateCryptoContextForAlgorithm( + NSSTrustDomain *td, + NSSOID *algorithm) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} + +NSS_IMPLEMENT NSSCryptoContext * +NSSTrustDomain_CreateCryptoContextForAlgorithmAndParameters( + NSSTrustDomain *td, + NSSAlgorithmAndParameters *ap) +{ + nss_SetError(NSS_ERROR_NOT_FOUND); + return NULL; +} |