/* * If zero is true, zeroize the arena memory before freeing it. */ void PORT_FreeArena(PLArenaPool *arena, PRBool zero) { PORTArenaPool *pool = (PORTArenaPool *)arena; PRLock * lock = (PRLock *)0; size_t len = sizeof *arena; static PRBool checkedEnv = PR_FALSE; static PRBool doFreeArenaPool = PR_FALSE; if (!pool) return; if (ARENAPOOL_MAGIC == pool->magic ) { len = sizeof *pool; lock = pool->lock; PZ_Lock(lock); } if (!checkedEnv) { /* no need for thread protection here */ doFreeArenaPool = (PR_GetEnv("NSS_DISABLE_ARENA_FREE_LIST") == NULL); checkedEnv = PR_TRUE; } if (zero) { PL_ClearArenaPool(arena, 0); } if (doFreeArenaPool) { PL_FreeArenaPool(arena); } else { PL_FinishArenaPool(arena); } PORT_ZFree(arena, len); if (lock) { PZ_Unlock(lock); PZ_DestroyLock(lock); } }
/* InitSessionCacheLocks is called, protected by lockOnce, to create the * session cache locks. */ static PRStatus InitSessionCacheLocks(void) { SECStatus rv; cacheLock = PZ_NewLock(nssILockCache); if (cacheLock == NULL) { return PR_FAILURE; } rv = ssl_InitSymWrapKeysLock(); if (rv != SECSuccess) { PRErrorCode error = PORT_GetError(); PZ_DestroyLock(cacheLock); cacheLock = NULL; PORT_SetError(error); return PR_FAILURE; } rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL); PORT_Assert(SECSuccess == rv); if (SECSuccess != rv) { return PR_FAILURE; } return PR_SUCCESS; }
/* cleanup at shutdown */ void RSA_Cleanup(void) { if (!coBPInit.initialized) return; while (!PR_CLIST_IS_EMPTY(&blindingParamsList.head)) { struct RSABlindingParamsStr * rsabp = (struct RSABlindingParamsStr *) PR_LIST_HEAD(&blindingParamsList.head); PR_REMOVE_LINK(&rsabp->link); mp_clear(&rsabp->f); mp_clear(&rsabp->g); SECITEM_FreeItem(&rsabp->modulus,PR_FALSE); PORT_Free(rsabp); } if (blindingParamsList.lock) { PZ_DestroyLock(blindingParamsList.lock); blindingParamsList.lock = NULL; } coBPInit.initialized = 0; coBPInit.inProgress = 0; coBPInit.status = 0; }
/* cleanup at shutdown */ void RSA_Cleanup(void) { blindingParams * bp = NULL; if (!coBPInit.initialized) return; while (!PR_CLIST_IS_EMPTY(&blindingParamsList.head)) { RSABlindingParams *rsabp = (RSABlindingParams *)PR_LIST_HEAD(&blindingParamsList.head); PR_REMOVE_LINK(&rsabp->link); /* clear parameters cache */ while (rsabp->bp != NULL) { bp = rsabp->bp; rsabp->bp = rsabp->bp->next; mp_clear( &bp->f ); mp_clear( &bp->g ); } SECITEM_FreeItem(&rsabp->modulus,PR_FALSE); PORT_Free(rsabp); } if (blindingParamsList.cVar) { PR_DestroyCondVar(blindingParamsList.cVar); blindingParamsList.cVar = NULL; } if (blindingParamsList.lock) { SKIP_AFTER_FORK(PZ_DestroyLock(blindingParamsList.lock)); blindingParamsList.lock = NULL; } coBPInit.initialized = 0; coBPInit.inProgress = 0; coBPInit.status = 0; }
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; }
/* * If zero is true, zeroize the arena memory before freeing it. */ void PORT_FreeArena(PLArenaPool *arena, PRBool zero) { PORTArenaPool *pool = (PORTArenaPool *)arena; PRLock *lock = (PRLock *)0; size_t len = sizeof *arena; if (!pool) return; if (ARENAPOOL_MAGIC == pool->magic) { len = sizeof *pool; lock = pool->lock; PZ_Lock(lock); } if (zero) { PL_ClearArenaPool(arena, 0); } (void)PR_CallOnce(&setupUseFreeListOnce, &SetupUseFreeList); if (useFreeList) { PL_FreeArenaPool(arena); } else { PL_FinishArenaPool(arena); } PORT_ZFree(arena, len); if (lock) { PZ_Unlock(lock); PZ_DestroyLock(lock); } }
/* we can only get here if we've destroyed the module, or some one has * erroneously freed a slot that wasn't referenced. */ void SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) { PRBool willfree = PR_FALSE; if (fromSlot) { PORT_Assert(module->refCount == 0); PZ_Lock(module->refLock); if (module->slotCount-- == 1) { willfree = PR_TRUE; } PORT_Assert(willfree || (module->slotCount > 0)); PZ_Unlock(module->refLock); if (!willfree) return; } if (module == pendingModule) { pendingModule = NULL; } if (module->loaded) { SECMOD_UnloadModule(module); } PZ_DestroyLock(module->refLock); PORT_FreeArena(module->arena,PR_FALSE); secmod_PrivateModuleCount--; }
static PRStatus rng_init(void) { PRUint8 bytes[PRNG_SEEDLEN * 2]; /* entropy + nonce */ unsigned int numBytes; SECStatus rv = SECSuccess; if (globalrng == NULL) { /* bytes needs to have enough space to hold * a SHA256 hash value. Blow up at compile time if this isn't true */ PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH); /* create a new global RNG context */ globalrng = &theGlobalRng; PORT_Assert(NULL == globalrng->lock); /* create a lock for it */ globalrng->lock = PZ_NewLock(nssILockOther); if (globalrng->lock == NULL) { globalrng = NULL; PORT_SetError(PR_OUT_OF_MEMORY_ERROR); return PR_FAILURE; } /* Try to get some seed data for the RNG */ numBytes = (unsigned int)RNG_SystemRNG(bytes, sizeof bytes); PORT_Assert(numBytes == 0 || numBytes == sizeof bytes); if (numBytes != 0) { /* if this is our first call, instantiate, otherwise reseed * prng_instantiate gets a new clean state, we want to mix * any previous entropy we may have collected */ if (V(globalrng)[0] == 0) { rv = prng_instantiate(globalrng, bytes, numBytes); } else { rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0); } memset(bytes, 0, numBytes); } else { PZ_DestroyLock(globalrng->lock); globalrng->lock = NULL; globalrng = NULL; return PR_FAILURE; } if (rv != SECSuccess) { return PR_FAILURE; } /* the RNG is in a valid state */ globalrng->isValid = PR_TRUE; globalrng->isKatTest = PR_FALSE; /* fetch one random value so that we can populate rng->oldV for our * continous random number test. */ prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0); /* Fetch more entropy into the PRNG */ RNG_SystemInfoForRNG(); } return PR_SUCCESS; }
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; }
static SECStatus ssl_FreeClientSessionCacheLock(void) { if (cacheLock) { PZ_DestroyLock(cacheLock); cacheLock = NULL; return SECSuccess; } PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return SECFailure; }
/* * Free up a Cipher Context */ void PK11_DestroyContext(PK11Context *context, PRBool freeit) { pk11_CloseSession(context->slot,context->session,context->ownSession); /* initialize the critical fields of the context */ if (context->savedData != NULL ) PORT_Free(context->savedData); if (context->key) PK11_FreeSymKey(context->key); if (context->param && context->param != &pk11_null_params) SECITEM_FreeItem(context->param, PR_TRUE); if (context->sessionLock) PZ_DestroyLock(context->sessionLock); PK11_FreeSlot(context->slot); if (freeit) PORT_Free(context); }
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); } }
/* * If zero is true, zeroize the arena memory before freeing it. */ void PORT_FreeArena(PLArenaPool *arena, PRBool zero) { PORTArenaPool *pool = (PORTArenaPool *)arena; PRLock * lock = (PRLock *)0; size_t len = sizeof *arena; extern const PRVersionDescription * libVersionPoint(void); static const PRVersionDescription * pvd; static PRBool doFreeArenaPool = PR_FALSE; if (ARENAPOOL_MAGIC == pool->magic ) { len = sizeof *pool; lock = pool->lock; PZ_Lock(lock); } if (!pvd) { /* Each of NSPR's DLLs has a function libVersionPoint(). ** We could do a lot of extra work to be sure we're calling the ** one in the DLL that holds PR_FreeArenaPool, but instead we ** rely on the fact that ALL NSPR DLLs in the same directory ** must be from the same release, and we call which ever one we get. */ /* no need for thread protection here */ pvd = libVersionPoint(); if ((pvd->vMajor > 4) || (pvd->vMajor == 4 && pvd->vMinor > 1) || (pvd->vMajor == 4 && pvd->vMinor == 1 && pvd->vPatch >= 1)) { const char *ev = PR_GetEnv("NSS_DISABLE_ARENA_FREE_LIST"); if (!ev) doFreeArenaPool = PR_TRUE; } } if (zero) { PLArena *a; for (a = arena->first.next; a; a = a->next) { PR_ASSERT(a->base <= a->avail && a->avail <= a->limit); memset((void *)a->base, 0, a->avail - a->base); } } if (doFreeArenaPool) { PL_FreeArenaPool(arena); } else { PL_FinishArenaPool(arena); } PORT_ZFree(arena, len); if (lock) { PZ_Unlock(lock); PZ_DestroyLock(lock); } }
/* * Clean up the global RNG context */ static void prng_freeRNGContext(RNGContext *rng) { PRUint8 inputhash[VSize(rng) + (sizeof rng->C)]; /* destroy context lock */ SKIP_AFTER_FORK(PZ_DestroyLock(globalrng->lock)); /* zero global RNG context except for C & V to preserve entropy */ prng_Hash_df(inputhash, sizeof rng->C, rng->C, sizeof rng->C, NULL, 0); prng_Hash_df(&inputhash[sizeof rng->C], VSize(rng), V(rng), VSize(rng), NULL, 0); memset(rng, 0, sizeof *rng); memcpy(rng->C, inputhash, sizeof rng->C); memcpy(V(rng), &inputhash[sizeof rng->C], VSize(rng)); memset(inputhash, 0, sizeof inputhash); }
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 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; }
/* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys * the session cache locks on shutdown and resets them to their initial * state. */ static SECStatus FreeSessionCacheLocks(void* appData, void* nssData) { static const PRCallOnceType pristineCallOnce; SECStatus rv; if (!cacheLock) { PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return SECFailure; } PZ_DestroyLock(cacheLock); cacheLock = NULL; rv = ssl_FreeSymWrapKeysLock(); if (rv != SECSuccess) { return rv; } lockOnce = pristineCallOnce; return SECSuccess; }
/* 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; }
CK_RV PR_CALLBACK secmodDestroyMutext(CK_VOID_PTR mutext) { PZ_DestroyLock((PZLock *)mutext); return CKR_OK; }