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; }
/* # 379 "arena.c" */ NSSArena * NSSArena_Create ( void ) { nss_ClearErrorStack(); return nssArena_Create(); }
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; }
/* * nssHash_create * */ NSS_IMPLEMENT nssHash * nssHash_Create ( NSSArena *arenaOpt, PRUint32 numBuckets, PLHashFunction keyHash, PLHashComparator keyCompare, PLHashComparator valueCompare ) { nssHash *rv; NSSArena *arena; PRBool i_alloced; #ifdef NSSDEBUG if( arenaOpt && PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) { nss_SetError(NSS_ERROR_INVALID_POINTER); return (nssHash *)NULL; } #endif /* NSSDEBUG */ if (arenaOpt) { arena = arenaOpt; i_alloced = PR_FALSE; } else { arena = nssArena_Create(); i_alloced = PR_TRUE; } rv = nss_ZNEW(arena, nssHash); if( (nssHash *)NULL == rv ) { goto loser; } rv->mutex = PZ_NewLock(nssILockOther); if( (PZLock *)NULL == rv->mutex ) { goto loser; } rv->plHashTable = PL_NewHashTable(numBuckets, keyHash, keyCompare, valueCompare, &nssArenaHashAllocOps, arena); if( (PLHashTable *)NULL == rv->plHashTable ) { (void)PZ_DestroyLock(rv->mutex); goto loser; } rv->count = 0; rv->arena = arena; rv->i_alloced_arena = i_alloced; return rv; loser: (void)nss_ZFreeIf(rv); return (nssHash *)NULL; }
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 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; }
/* 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; }
/* 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; }
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; }