NSSToken * nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSToken *rvToken; NSSArena *arena; /* Don't create a token object for a disabled slot */ if (nss3slot->disabled) { PORT_SetError(SEC_ERROR_NO_TOKEN); return NULL; } 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); if (!rvToken->base.lock) { nssArena_Destroy(arena); return NULL; } rvToken->base.arena = arena; rvToken->pk11slot = nss3slot; rvToken->epv = nss3slot->functionList; rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); /* continue, even if rvToken->defaultSession is NULL */ if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) { rvToken->cache = nssTokenObjectCache_Create(rvToken, PR_TRUE, PR_TRUE, PR_TRUE); if (!rvToken->cache) goto loser; } 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); if (!rvToken->slot) { goto loser; } rvToken->slot->token = rvToken; if (rvToken->defaultSession) rvToken->defaultSession->slot = rvToken->slot; return rvToken; loser: PZ_DestroyLock(rvToken->base.lock); nssArena_Destroy(arena); return NULL; }
NSS_IMPLEMENT NSSCryptoContext * nssCryptoContext_Create ( NSSTrustDomain *td, NSSCallback *uhhOpt ) { NSSArena *arena; NSSCryptoContext *rvCC; arena = NSSArena_Create(); if (!arena) { return NULL; } rvCC = nss_ZNEW(arena, NSSCryptoContext); if (!rvCC) { return NULL; } rvCC->td = td; rvCC->arena = arena; rvCC->certStore = nssCertificateStore_Create(rvCC->arena); if (!rvCC->certStore) { nssArena_Destroy(arena); return NULL; } return rvCC; }
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; }
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 NSSSlot * nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSSlot *rvSlot; 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; /* Grab the slot name from the PKCS#11 fixed-length buffer */ rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name,td->arena); rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock; return rvSlot; }
/* CERT_TraversePermCertsForNickname */ NSS_IMPLEMENT PRStatus nssTrustDomain_TraverseCertificatesByNickname ( NSSTrustDomain *td, NSSUTF8 *nickname, PRStatus (*callback)(NSSCertificate *c, void *arg), void *arg ) { PRStatus nssrv = PR_SUCCESS; NSSArena *tmpArena; NSSCertificate **nickCerts; NSSCertificate *c; PRIntn i; tmpArena = NSSArena_Create(); if (!tmpArena) { return PR_FAILURE; } nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL, 0, tmpArena); if (nickCerts) { for (i=0, c = nickCerts[i]; c; i++) { nssrv = callback(c, arg); if (nssrv != PR_SUCCESS) break; } } nssArena_Destroy(tmpArena); return nssrv; }
NSS_IMPLEMENT PRStatus nssTrustDomain_DestroyCache ( NSSTrustDomain *td ) { if (!td->cache) { nss_SetError(NSS_ERROR_INTERNAL_ERROR); return PR_FAILURE; } if (nssHash_Count(td->cache->issuerAndSN) > 0) { nss_SetError(NSS_ERROR_BUSY); return PR_FAILURE; } PZ_DestroyLock(td->cache->lock); nssHash_Destroy(td->cache->issuerAndSN); nssHash_Destroy(td->cache->subject); nssHash_Destroy(td->cache->nickname); nssHash_Destroy(td->cache->email); nssArena_Destroy(td->cache->arena); td->cache = NULL; #ifdef DEBUG_CACHE PR_LOG(s_log, PR_LOG_DEBUG, ("Cache destroyed.")); #endif return PR_SUCCESS; }
NSS_IMPLEMENT nssCertificateStore * nssCertificateStore_Create ( NSSArena *arenaOpt ) { NSSArena *arena; nssCertificateStore *store; PRBool i_alloced_arena; if (arenaOpt) { arena = arenaOpt; i_alloced_arena = PR_FALSE; } else { arena = nssArena_Create(); if (!arena) { return NULL; } i_alloced_arena = PR_TRUE; } store = nss_ZNEW(arena, nssCertificateStore); if (!store) { goto loser; } store->lock = PZ_NewLock(nssILockOther); if (!store->lock) { goto loser; } /* Create the issuer/serial --> {cert, trust, S/MIME profile } hash */ store->issuer_and_serial = nssHash_CreateCertificate(arena, 0); if (!store->issuer_and_serial) { goto loser; } /* Create the subject DER --> subject list hash */ store->subject = nssHash_CreateItem(arena, 0); if (!store->subject) { goto loser; } store->arena = arena; store->i_alloced_arena = i_alloced_arena; return store; loser: if (store) { if (store->lock) { PZ_DestroyLock(store->lock); } if (store->issuer_and_serial) { nssHash_Destroy(store->issuer_and_serial); } if (store->subject) { nssHash_Destroy(store->subject); } } if (i_alloced_arena) { nssArena_Destroy(arena); } return NULL; }
NSS_IMPLEMENT PRStatus nssCertificate_Destroy ( NSSCertificate *c ) { nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; if (c) { PRUint32 i; nssDecodedCert *dc = c->decoding; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSCryptoContext *cc = c->object.cryptoContext; PR_ASSERT(c->object.refCount > 0); /* --- LOCK storage --- */ if (cc) { nssCertificateStore_Lock(cc->certStore, &lockTrace); } else { nssTrustDomain_LockCertCache(td); } if (PR_ATOMIC_DECREMENT(&c->object.refCount) == 0) { /* --- remove cert and UNLOCK storage --- */ if (cc) { nssCertificateStore_RemoveCertLOCKED(cc->certStore, c); nssCertificateStore_Unlock(cc->certStore, &lockTrace, &unlockTrace); } else { nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); nssTrustDomain_UnlockCertCache(td); } /* free cert data */ for (i=0; i<c->object.numInstances; i++) { nssCryptokiObject_Destroy(c->object.instances[i]); } nssPKIObject_DestroyLock(&c->object); nssArena_Destroy(c->object.arena); nssDecodedCert_Destroy(dc); } else { /* --- UNLOCK storage --- */ if (cc) { nssCertificateStore_Unlock(cc->certStore, &lockTrace, &unlockTrace); } else { nssTrustDomain_UnlockCertCache(td); } } } return PR_SUCCESS; }
NSS_IMPLEMENT PRStatus nssSlot_Destroy ( NSSSlot *slot ) { if (slot) { if (PR_AtomicDecrement(&slot->base.refCount) == 0) { PZ_DestroyLock(slot->base.lock); return nssArena_Destroy(slot->base.arena); } } return PR_SUCCESS; }
/* * nssHash_Destroy * */ NSS_IMPLEMENT void nssHash_Destroy ( nssHash *hash ) { (void)PZ_DestroyLock(hash->mutex); PL_HashTableDestroy(hash->plHashTable); if (hash->i_alloced_arena) { nssArena_Destroy(hash->arena); } else { nss_ZFreeIf(hash); } }
/* # 476 "arena.c" */ PRStatus NSSArena_Destroy ( NSSArena *arena ) { nss_ClearErrorStack(); return nssArena_Destroy(arena); }
NSS_IMPLEMENT PRStatus nssToken_Destroy ( NSSToken *tok ) { if (tok) { if (PR_ATOMIC_DECREMENT(&tok->base.refCount) == 0) { PZ_DestroyLock(tok->base.lock); nssTokenObjectCache_Destroy(tok->cache); /* The token holds the first/last reference to the slot. * When the token is actually destroyed, that ref must go too. */ (void)nssSlot_Destroy(tok->slot); return nssArena_Destroy(tok->base.arena); } } return PR_SUCCESS; }
NSS_IMPLEMENT PRStatus NSSCryptoContext_Destroy ( NSSCryptoContext *cc ) { PRStatus status = PR_SUCCESS; PORT_Assert(cc->certStore); if (cc->certStore) { status = nssCertificateStore_Destroy(cc->certStore); if (status == PR_FAILURE) { return status; } } else { status = PR_FAILURE; } nssArena_Destroy(cc->arena); return status; }
NSS_IMPLEMENT PRStatus nssCertificateStore_Destroy ( nssCertificateStore *store ) { if (nssHash_Count(store->issuer_and_serial) > 0) { nss_SetError(NSS_ERROR_BUSY); return PR_FAILURE; } PZ_DestroyLock(store->lock); nssHash_Destroy(store->issuer_and_serial); nssHash_Destroy(store->subject); if (store->i_alloced_arena) { nssArena_Destroy(store->arena); } else { nss_ZFreeIf(store); } return PR_SUCCESS; }
NSS_IMPLEMENT nssSMIMEProfile * nssSMIMEProfile_Create ( NSSCertificate *cert, NSSItem *profileTime, NSSItem *profileData ) { NSSArena *arena; nssSMIMEProfile *rvProfile; nssPKIObject *object; NSSTrustDomain *td = nssCertificate_GetTrustDomain(cert); NSSCryptoContext *cc = nssCertificate_GetCryptoContext(cert); arena = nssArena_Create(); if (!arena) { return NULL; } object = nssPKIObject_Create(arena, NULL, td, cc, nssPKILock); if (!object) { goto loser; } rvProfile = nss_ZNEW(arena, nssSMIMEProfile); if (!rvProfile) { goto loser; } rvProfile->object = *object; rvProfile->certificate = cert; rvProfile->email = nssUTF8_Duplicate(cert->email, arena); rvProfile->subject = nssItem_Duplicate(&cert->subject, arena, NULL); if (profileTime) { rvProfile->profileTime = nssItem_Duplicate(profileTime, arena, NULL); } if (profileData) { rvProfile->profileData = nssItem_Duplicate(profileData, arena, NULL); } return rvProfile; loser: if (object) nssPKIObject_Destroy(object); else if (arena) nssArena_Destroy(arena); return (nssSMIMEProfile *)NULL; }
NSS_IMPLEMENT void nssTrustDomain_RemoveCertFromCacheLOCKED ( NSSTrustDomain *td, NSSCertificate *cert ) { nssList *subjectList; cache_entry *ce; NSSArena *arena; NSSUTF8 *nickname; #ifdef DEBUG_CACHE log_cert_ref("attempt to remove cert", cert); #endif ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, cert); if (!ce || ce->entry.cert != cert) { /* If it's not in the cache, or a different cert is (this is really * for safety reasons, though it shouldn't happen), do nothing */ #ifdef DEBUG_CACHE PR_LOG(s_log, PR_LOG_DEBUG, ("but it wasn't in the cache")); #endif return; } (void)remove_issuer_and_serial_entry(td->cache, cert); (void)remove_subject_entry(td->cache, cert, &subjectList, &nickname, &arena); if (nssList_Count(subjectList) == 0) { (void)remove_nickname_entry(td->cache, nickname, subjectList); (void)remove_email_entry(td->cache, cert, subjectList); (void)nssList_Destroy(subjectList); nssHash_Remove(td->cache->subject, &cert->subject); /* there are no entries left for this subject, free the space used * for both the nickname and subject entries */ if (arena) { nssArena_Destroy(arena); } } }
static PRStatus remove_email_entry( nssTDCertificateCache *cache, NSSCertificate *cert, nssList *subjectList) { PRStatus nssrv = PR_FAILURE; cache_entry *ce; /* Find the subject list in the email hash */ if (cert->email) { ce = (cache_entry *)nssHash_Lookup(cache->email, cert->email); if (ce) { nssList *subjects = ce->entry.list; /* Remove the subject list from the email hash */ if (subjects) { nssList_Remove(subjects, subjectList); #ifdef DEBUG_CACHE log_item_dump("removed subject list", &cert->subject); PR_LOG(s_log, PR_LOG_DEBUG, ("for email %s", cert->email)); #endif if (nssList_Count(subjects) == 0) { /* No more subject lists for email, delete list and * remove hash entry */ (void)nssList_Destroy(subjects); nssHash_Remove(cache->email, cert->email); /* there are no entries left for this address, free space * used for email entries */ nssArena_Destroy(ce->arena); #ifdef DEBUG_CACHE PR_LOG(s_log, PR_LOG_DEBUG, ("removed email %s", cert->email)); #endif } } nssrv = PR_SUCCESS; } } return nssrv; }
/* this should not be exposed in a header, but is here to keep the above * types/functions static */ NSS_IMPLEMENT PRStatus nssTrustDomain_InitializeCache ( NSSTrustDomain *td, PRUint32 cacheSize ) { NSSArena *arena; nssTDCertificateCache *cache = td->cache; #ifdef DEBUG_CACHE s_log = PR_NewLogModule("nss_cache"); PR_ASSERT(s_log); #endif PR_ASSERT(!cache); arena = nssArena_Create(); if (!arena) { return PR_FAILURE; } cache = nss_ZNEW(arena, nssTDCertificateCache); if (!cache) { nssArena_Destroy(arena); return PR_FAILURE; } cache->lock = PZ_NewLock(nssILockCache); if (!cache->lock) { nssArena_Destroy(arena); return PR_FAILURE; } /* Create the issuer and serial DER --> certificate hash */ cache->issuerAndSN = nssHash_CreateCertificate(arena, cacheSize); if (!cache->issuerAndSN) { goto loser; } /* Create the subject DER --> subject list hash */ cache->subject = nssHash_CreateItem(arena, cacheSize); if (!cache->subject) { goto loser; } /* Create the nickname --> subject list hash */ cache->nickname = nssHash_CreateString(arena, cacheSize); if (!cache->nickname) { goto loser; } /* Create the email --> list of subject lists hash */ cache->email = nssHash_CreateString(arena, cacheSize); if (!cache->email) { goto loser; } cache->arena = arena; td->cache = cache; #ifdef DEBUG_CACHE PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialized.")); #endif return PR_SUCCESS; loser: PZ_DestroyLock(cache->lock); nssArena_Destroy(arena); td->cache = NULL; #ifdef DEBUG_CACHE PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialization failed.")); #endif return PR_FAILURE; }
/* Sigh. The methods to find objects declared above cause problems with * the low-level object cache in the softoken -- the objects are found in * toto, then one wave of GetAttributes is done, then another. Having a * large number of objects causes the cache to be thrashed, as the objects * are gone before there's any chance to ask for their attributes. * So, for now, bringing back traversal methods for certs. This way all of * the cert's attributes can be grabbed immediately after finding it, * increasing the likelihood that the cache takes care of it. */ NSS_IMPLEMENT PRStatus nssToken_TraverseCertificates ( NSSToken *token, nssSession *sessionOpt, nssTokenSearchType searchType, PRStatus (* callback)(nssCryptokiObject *instance, void *arg), void *arg ) { CK_RV ckrv; CK_ULONG count; CK_OBJECT_HANDLE *objectHandles; CK_ATTRIBUTE_PTR attr; CK_ATTRIBUTE cert_template[2]; CK_ULONG ctsize; NSSArena *arena; PRStatus status; PRUint32 arraySize, numHandles; nssCryptokiObject **objects; void *epv = nssToken_GetCryptokiEPV(token); nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession; /* Don't ask the module to use an invalid session handle. */ if (!session || session->handle == CK_INVALID_SESSION) { PORT_SetError(SEC_ERROR_NO_TOKEN); return PR_FAILURE; } /* template for all certs */ NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); if (searchType == nssTokenSearchType_SessionOnly) { NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); } else if (searchType == nssTokenSearchType_TokenOnly || searchType == nssTokenSearchType_TokenForced) { NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); } NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); /* the arena is only for the array of object handles */ arena = nssArena_Create(); if (!arena) { return PR_FAILURE; } arraySize = OBJECT_STACK_SIZE; numHandles = 0; objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize); if (!objectHandles) { goto loser; } nssSession_EnterMonitor(session); /* ==== session lock === */ /* Initialize the find with the template */ ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, cert_template, ctsize); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); goto loser; } while (PR_TRUE) { /* Issue the find for up to arraySize - numHandles objects */ ckrv = CKAPI(epv)->C_FindObjects(session->handle, objectHandles + numHandles, arraySize - numHandles, &count); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); goto loser; } /* bump the number of found objects */ numHandles += count; if (numHandles < arraySize) { break; } /* the array is filled, double it and continue */ arraySize *= 2; objectHandles = nss_ZREALLOCARRAY(objectHandles, CK_OBJECT_HANDLE, arraySize); if (!objectHandles) { nssSession_ExitMonitor(session); goto loser; } } ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); nssSession_ExitMonitor(session); /* ==== end session lock === */ if (ckrv != CKR_OK) { goto loser; } if (numHandles > 0) { objects = create_objects_from_handles(token, session, objectHandles, numHandles); if (objects) { nssCryptokiObject **op; for (op = objects; *op; op++) { status = (*callback)(*op, arg); } nss_ZFreeIf(objects); } } nssArena_Destroy(arena); return PR_SUCCESS; loser: nssArena_Destroy(arena); return PR_FAILURE; }
static NSSCertificate * find_cert_issuer ( NSSCertificate *c, NSSTime *timeOpt, NSSUsage *usage, NSSPolicies *policiesOpt, NSSTrustDomain *td, NSSCryptoContext *cc ) { NSSArena *arena; NSSCertificate **certs = NULL; NSSCertificate **ccIssuers = NULL; NSSCertificate **tdIssuers = NULL; NSSCertificate *issuer = NULL; if (!cc) cc = c->object.cryptoContext; if (!td) td = NSSCertificate_GetTrustDomain(c); arena = nssArena_Create(); if (!arena) { return (NSSCertificate *)NULL; } if (cc) { ccIssuers = nssCryptoContext_FindCertificatesBySubject(cc, &c->issuer, NULL, 0, arena); } if (td) tdIssuers = nssTrustDomain_FindCertificatesBySubject(td, &c->issuer, NULL, 0, arena); certs = nssCertificateArray_Join(ccIssuers, tdIssuers); if (certs) { nssDecodedCert *dc = NULL; void *issuerID = NULL; dc = nssCertificate_GetDecoding(c); if (dc) { issuerID = dc->getIssuerIdentifier(dc); } /* XXX review based on CERT_FindCertIssuer * this function is not using the authCertIssuer field as a fallback * if authority key id does not exist */ if (issuerID) { certs = filter_subject_certs_for_id(certs, issuerID); } certs = filter_certs_for_valid_issuers(certs); issuer = nssCertificateArray_FindBestCertificate(certs, timeOpt, usage, policiesOpt); nssCertificateArray_Destroy(certs); } nssArena_Destroy(arena); return issuer; }
NSS_EXTERN PRStatus STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) { PRStatus nssrv; NSSCertificate *c = STAN_GetNSSCertificate(cc); NSSToken *tok; NSSTrustDomain *td; NSSTrust *nssTrust; NSSArena *arena; CERTCertTrust *oldTrust; CERTCertTrust *newTrust; nssListIterator *tokens; PRBool moving_object; nssCryptokiObject *newInstance; nssPKIObject *pkiob; if (c == NULL) { return PR_FAILURE; } oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc); if (oldTrust) { if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) { /* ... and the new trust is no different, done) */ return PR_SUCCESS; } else { /* take over memory already allocated in cc's arena */ newTrust = oldTrust; } } else { newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); } memcpy(newTrust, trust, sizeof(CERTCertTrust)); CERT_LockCertTrust(cc); cc->trust = newTrust; CERT_UnlockCertTrust(cc); /* Set the NSSCerticate's trust */ arena = nssArena_Create(); if (!arena) return PR_FAILURE; nssTrust = nss_ZNEW(arena, NSSTrust); if (!nssTrust) { nssArena_Destroy(arena); return PR_FAILURE; } pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock); if (!pkiob) { nssArena_Destroy(arena); return PR_FAILURE; } nssTrust->object = *pkiob; nssTrust->certificate = c; nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE); nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE); nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE); nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE); nssTrust->stepUpApproved = (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA); if (c->object.cryptoContext != NULL) { /* The cert is in a context, set the trust there */ NSSCryptoContext *cc = c->object.cryptoContext; nssrv = nssCryptoContext_ImportTrust(cc, nssTrust); if (nssrv != PR_SUCCESS) { goto done; } if (c->object.numInstances == 0) { /* The context is the only instance, finished */ goto done; } } td = STAN_GetDefaultTrustDomain(); tok = stan_GetTrustToken(c); moving_object = PR_FALSE; if (tok && PK11_IsReadOnly(tok->pk11slot)) { NSSRWLock_LockRead(td->tokensLock); tokens = nssList_CreateIterator(td->tokenList); if (!tokens) { nssrv = PR_FAILURE; NSSRWLock_UnlockRead(td->tokensLock); goto done; } for (tok = (NSSToken *)nssListIterator_Start(tokens); tok != (NSSToken *)NULL; tok = (NSSToken *)nssListIterator_Next(tokens)) { if (!PK11_IsReadOnly(tok->pk11slot)) break; } nssListIterator_Finish(tokens); nssListIterator_Destroy(tokens); NSSRWLock_UnlockRead(td->tokensLock); moving_object = PR_TRUE; } if (tok) { if (moving_object) { /* this is kind of hacky. the softoken needs the cert * object in order to store trust. forcing it to be perm */ NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); NSSASCII7 *email = NULL; if (PK11_IsInternal(tok->pk11slot)) { email = c->email; } newInstance = nssToken_ImportCertificate(tok, NULL, NSSCertificateType_PKIX, &c->id, nickname, &c->encoding, &c->issuer, &c->subject, &c->serial, email, PR_TRUE); nss_ZFreeIf(nickname); nickname = NULL; if (!newInstance) { nssrv = PR_FAILURE; goto done; } nssPKIObject_AddInstance(&c->object, newInstance); } newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, &c->issuer, &c->serial, nssTrust->serverAuth, nssTrust->clientAuth, nssTrust->codeSigning, nssTrust->emailProtection, nssTrust->stepUpApproved, PR_TRUE); /* If the selected token can't handle trust, dump the trust on * the internal token */ if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); NSSASCII7 *email = c->email; tok = PK11Slot_GetNSSToken(slot); PK11_FreeSlot(slot); newInstance = nssToken_ImportCertificate(tok, NULL, NSSCertificateType_PKIX, &c->id, nickname, &c->encoding, &c->issuer, &c->subject, &c->serial, email, PR_TRUE); nss_ZFreeIf(nickname); nickname = NULL; if (!newInstance) { nssrv = PR_FAILURE; goto done; } nssPKIObject_AddInstance(&c->object, newInstance); newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, &c->issuer, &c->serial, nssTrust->serverAuth, nssTrust->clientAuth, nssTrust->codeSigning, nssTrust->emailProtection, nssTrust->stepUpApproved, PR_TRUE); } if (newInstance) { nssCryptokiObject_Destroy(newInstance); nssrv = PR_SUCCESS; } else { nssrv = PR_FAILURE; } } else { nssrv = PR_FAILURE; } done: (void)nssTrust_Destroy(nssTrust); return nssrv; }
NSS_EXTERN NSSCertificate * STAN_GetNSSCertificate(CERTCertificate *cc) { NSSCertificate *c; nssCryptokiInstance *instance; nssPKIObject *pkiob; NSSArena *arena; c = cc->nssCertificate; if (c) { return c; } /* i don't think this should happen. but if it can, need to create * NSSCertificate from CERTCertificate values here. */ /* Yup, it can happen. */ arena = NSSArena_Create(); if (!arena) { return NULL; } c = nss_ZNEW(arena, NSSCertificate); if (!c) { nssArena_Destroy(arena); return NULL; } NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert); c->type = NSSCertificateType_PKIX; pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor); if (!pkiob) { nssArena_Destroy(arena); return NULL; } c->object = *pkiob; nssItem_Create(arena, &c->issuer, cc->derIssuer.len, cc->derIssuer.data); nssItem_Create(arena, &c->subject, cc->derSubject.len, cc->derSubject.data); if (PR_TRUE) { /* CERTCertificate stores serial numbers decoded. I need the DER * here. sigh. */ SECItem derSerial; SECStatus secrv; secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); if (secrv == SECFailure) { nssArena_Destroy(arena); return NULL; } nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data); PORT_Free(derSerial.data); } if (cc->emailAddr && cc->emailAddr[0]) { c->email = nssUTF8_Create(arena, nssStringType_PrintableString, (NSSUTF8 *)cc->emailAddr, PORT_Strlen(cc->emailAddr)); } if (cc->slot) { instance = nss_ZNEW(arena, nssCryptokiInstance); if (!instance) { nssArena_Destroy(arena); return NULL; } instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot)); instance->handle = cc->pkcs11ID; instance->isTokenObject = PR_TRUE; if (cc->nickname) { instance->label = nssUTF8_Create(arena, nssStringType_UTF8String, (NSSUTF8 *)cc->nickname, PORT_Strlen(cc->nickname)); } nssPKIObject_AddInstance(&c->object, instance); } c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc); cc->nssCertificate = c; return c; }