Beispiel #1
0
void
PORT_ArenaUnmark(PLArenaPool *arena, void *mark)
{
#ifdef THREADMARK
    PORTArenaPool *pool = (PORTArenaPool *)arena;
    if (ARENAPOOL_MAGIC == pool->magic) {
        threadmark_mark **pw;

        PZ_Lock(pool->lock);

        if (PR_GetCurrentThread() != pool->marking_thread) {
            PZ_Unlock(pool->lock);
            PORT_SetError(SEC_ERROR_NO_MEMORY);
            PORT_Assert(0);
            return /* no error indication available */;
        }

        pw = &pool->first_mark;
        while (((threadmark_mark *)NULL != *pw) && (mark != (*pw)->mark)) {
            pw = &(*pw)->next;
        }

        if ((threadmark_mark *)NULL == *pw) {
            /* bad mark */
            PZ_Unlock(pool->lock);
            PORT_SetError(SEC_ERROR_NO_MEMORY);
            PORT_Assert(0);
            return /* no error indication available */;
        }

        *pw = (threadmark_mark *)NULL;

        if (!pool->first_mark) {
            pool->marking_thread = (PRThread *)NULL;
        }

        PZ_Unlock(pool->lock);
    }
#endif /* THREADMARK */
}
Beispiel #2
0
void *
PORT_ArenaAlloc(PLArenaPool *arena, size_t size)
{
    void *p = NULL;

    PORTArenaPool *pool = (PORTArenaPool *)arena;

    if (size <= 0) {
        size = 1;
    }

    if (size > MAX_SIZE) {
        /* you lose. */
    } else
        /* Is it one of ours?  Assume so and check the magic */
        if (ARENAPOOL_MAGIC == pool->magic) {
        PZ_Lock(pool->lock);
#ifdef THREADMARK
        /* Most likely one of ours.  Is there a thread id? */
        if (pool->marking_thread &&
            pool->marking_thread != PR_GetCurrentThread()) {
            /* Another thread holds a mark in this arena */
            PZ_Unlock(pool->lock);
            PORT_SetError(SEC_ERROR_NO_MEMORY);
            PORT_Assert(0);
            return NULL;
        } /* tid != null */
#endif    /* THREADMARK */
        PL_ARENA_ALLOCATE(p, arena, size);
        PZ_Unlock(pool->lock);
    } else {
        PL_ARENA_ALLOCATE(p, arena, size);
    }

    if (!p) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
    }

    return (p);
}
Beispiel #3
0
NSS_EXTERN PRStatus
nssCertificateStore_AddSMIMEProfile (
  nssCertificateStore *store,
  nssSMIMEProfile *profile
)
{
    NSSCertificate *cert;
    certificate_hash_entry *entry;
    cert = profile->certificate;
    PZ_Lock(store->lock);
    entry = (certificate_hash_entry *)
                              nssHash_Lookup(store->issuer_and_serial, cert);
    if (entry) {
	nssSMIMEProfile* newProfile = nssSMIMEProfile_AddRef(profile);
	if (entry->profile) {
	    nssSMIMEProfile_Destroy(entry->profile);
	}
	entry->profile = newProfile;
    }
    PZ_Unlock(store->lock);
    return (entry) ? PR_SUCCESS : PR_FAILURE;
}
Beispiel #4
0
void
terminateWorkerThreads(void)
{
    VLOG(("selfserv: server_thead: waiting on stopping"));
    PZ_Lock(qLock);
    PZ_NotifyAllCondVar(jobQNotEmptyCv);
    while (threadCount > 0) {
	PZ_WaitCondVar(threadCountChangeCv, PR_INTERVAL_NO_TIMEOUT);
    }
    /* The worker threads empty the jobQ before they terminate. */
    PORT_Assert(PR_CLIST_IS_EMPTY(&jobQ));
    PZ_Unlock(qLock); 

    DESTROY_CONDVAR(jobQNotEmptyCv);
    DESTROY_CONDVAR(freeListNotEmptyCv);
    DESTROY_CONDVAR(threadCountChangeCv);

    PR_DestroyLock(lastLoadedCrlLock);
    DESTROY_LOCK(qLock);
    PR_Free(jobTable);
    PR_Free(threads);
}
Beispiel #5
0
void *
PORT_ArenaGrow(PLArenaPool *arena, void *ptr, size_t oldsize, size_t newsize)
{
    PORTArenaPool *pool = (PORTArenaPool *)arena;
    PORT_Assert(newsize >= oldsize);

    if (newsize > MAX_SIZE) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return NULL;
    }

    if (ARENAPOOL_MAGIC == pool->magic) {
        PZ_Lock(pool->lock);
        /* Do we do a THREADMARK check here? */
        PL_ARENA_GROW(ptr, arena, oldsize, (newsize - oldsize));
        PZ_Unlock(pool->lock);
    } else {
        PL_ARENA_GROW(ptr, arena, oldsize, (newsize - oldsize));
    }

    return (ptr);
}
Beispiel #6
0
/*
 * stub files for legacy db's to be able to encrypt and decrypt
 * various keys and attributes.
 */
static SECStatus
sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText,
		    SECItem **cipherText)
{
    SFTKDBHandle *handle = sdb->app_private;
    SECStatus rv;

    if (handle == NULL) {
	return SECFailure;
    }

    /* if we aren't the key handle, try the other handle */
    if (handle->type != SFTK_KEYDB_TYPE) {
	handle = handle->peerDB;
    }

    /* not a key handle */
    if (handle == NULL || handle->passwordLock == NULL) {
	return SECFailure;
    }

    PZ_Lock(handle->passwordLock);
    if (handle->passwordKey.data == NULL) {
	PZ_Unlock(handle->passwordLock);
	/* PORT_SetError */
	return SECFailure;
    }
#if defined(PKCS11_DB_DATA_KEY_USE_KEYSTORE) || defined(PKCS11_DB_DATA_KEY_USE_KEYCHAIN)
	rv = sftkdb_EncryptAttributeByDbDataKey(arena,
			plainText, cipherText);
#else
    rv = sftkdb_EncryptAttribute(arena, 
	handle->newKey?handle->newKey:&handle->passwordKey, 
	plainText, cipherText);
#endif
    PZ_Unlock(handle->passwordLock);

    return rv;
}
Beispiel #7
0
NSS_EXTERN PRStatus
nssCertificateStore_AddTrust (
  nssCertificateStore *store,
  NSSTrust *trust
)
{
    NSSCertificate *cert;
    certificate_hash_entry *entry;
    cert = trust->certificate;
    PZ_Lock(store->lock);
    entry = (certificate_hash_entry *)
                              nssHash_Lookup(store->issuer_and_serial, cert);
    if (entry) {
	NSSTrust* newTrust = nssTrust_AddRef(trust);
	if (entry->trust) {
	    nssTrust_Destroy(entry->trust);
	}
	entry->trust = newTrust;
    }
    PZ_Unlock(store->lock);
    return (entry) ? PR_SUCCESS : PR_FAILURE;
}
Beispiel #8
0
/*
** Update the global random number generator with more seeding
** material.
*/
SECStatus 
RNG_RandomUpdate(const void *data, size_t bytes)
{
    SECStatus rv;

    /* Make sure our assumption that size_t is unsigned is true */
    PR_STATIC_ASSERT(((size_t)-1) > (size_t)1);

#if defined(NS_PTR_GT_32) || (defined(NSS_USE_64) && !defined(NS_PTR_LE_32))
    /*
     * NIST 800-90 requires us to verify our inputs. This value can
     * come from the application, so we need to make sure it's within the
     * spec. The spec says it must be less than 2^32 bytes (2^35 bits).
     * This can only happen if size_t is greater than 32 bits (i.e. on
     * most 64 bit platforms). The 90% case (perhaps 100% case), size_t
     * is less than or equal to 32 bits if the platform is not 64 bits, and
     * greater than 32 bits if it is a 64 bit platform. The corner
     * cases are handled with explicit defines NS_PTR_GT_32 and NS_PTR_LE_32.
     *
     * In general, neither NS_PTR_GT_32 nor NS_PTR_LE_32 will need to be 
     * defined. If you trip over the next two size ASSERTS at compile time,
     * you will need to define them for your platform.
     *
     * if 'sizeof(size_t) > 4' is triggered it means that we were expecting
     *   sizeof(size_t) to be greater than 4, but it wasn't. Setting 
     *   NS_PTR_LE_32 will correct that mistake.
     *
     * if 'sizeof(size_t) <= 4' is triggered, it means that we were expecting
     *   sizeof(size_t) to be less than or equal to 4, but it wasn't. Setting 
     *   NS_PTR_GT_32 will correct that mistake.
     */

    PR_STATIC_ASSERT(sizeof(size_t) > 4);

    if (bytes > PRNG_MAX_ADDITIONAL_BYTES) {
	bytes = PRNG_MAX_ADDITIONAL_BYTES;
    }
#else
    PR_STATIC_ASSERT(sizeof(size_t) <= 4);
#endif

    PZ_Lock(globalrng->lock);
    /* if we're passed more than our additionalDataCache, simply
     * call reseed with that data */
    if (bytes > sizeof (globalrng->additionalDataCache)) {
	rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int) bytes);
    /* if we aren't going to fill or overflow the buffer, just cache it */
    } else if (bytes < ((sizeof globalrng->additionalDataCache)
				- globalrng->additionalAvail)) {
	PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail,
		    data, bytes);
	globalrng->additionalAvail += (PRUint32) bytes;
	rv = SECSuccess;
    } else {
	/* we are going to fill or overflow the buffer. In this case we will
	 * fill the entropy buffer, reseed with it, start a new buffer with the
	 * remainder. We know the remainder will fit in the buffer because
	 * we already handled the case where bytes > the size of the buffer.
	 */
	size_t bufRemain = (sizeof globalrng->additionalDataCache) 
					- globalrng->additionalAvail;
	/* fill the rest of the buffer */
	if (bufRemain) {
	    PORT_Memcpy(globalrng->additionalDataCache
			+globalrng->additionalAvail, 
			data, bufRemain);
	    data = ((unsigned char *)data) + bufRemain;
	    bytes -= bufRemain;
	}
	/* reseed from buffer */
	rv = prng_reseed_test(globalrng, NULL, 0, 
				        globalrng->additionalDataCache, 
					sizeof globalrng->additionalDataCache);

	/* copy the rest into the cache */
	PORT_Memcpy(globalrng->additionalDataCache, data, bytes);
	globalrng->additionalAvail = (PRUint32) bytes;
    }
		
    PZ_Unlock(globalrng->lock);
    return rv;
}
Beispiel #9
0
SECStatus
launch_threads(
    startFn *startFunc,
    PRFileDesc *a,
    PRFileDesc *b,
    int c,
    PRBool local)
{
    int i;
    SECStatus rv = SECSuccess;

    /* create the thread management serialization structs */
    qLock = PZ_NewLock(nssILockSelfServ);
    jobQNotEmptyCv = PZ_NewCondVar(qLock);
    freeListNotEmptyCv = PZ_NewCondVar(qLock);
    threadCountChangeCv = PZ_NewCondVar(qLock);

    /* create monitor for crl reload procedure */
    lastLoadedCrlLock = PR_NewLock();

    /* allocate the array of thread slots */
    threads = PR_Calloc(maxThreads, sizeof(perThread));
    if (NULL == threads) {
        fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n");
        return SECFailure;
    }
    /* 5 is a little extra, intended to keep the jobQ from underflowing.
    ** That is, from going empty while not stopping and clients are still
    ** trying to contact us.
    */
    rv = setupJobs(maxThreads + 5);
    if (rv != SECSuccess)
        return rv;

    PZ_Lock(qLock);
    for (i = 0; i < maxThreads; ++i) {
        perThread *slot = threads + i;

        slot->state = rs_running;
        slot->a = a;
        slot->b = b;
        slot->c = c;
        slot->startFunc = startFunc;
        slot->prThread = PR_CreateThread(PR_USER_THREAD,
                                         thread_wrapper, slot, PR_PRIORITY_NORMAL,
                                         (PR_TRUE ==
                                          local)
                                             ? PR_LOCAL_THREAD
                                             : PR_GLOBAL_THREAD,
                                         PR_JOINABLE_THREAD, 0);
        if (slot->prThread == NULL) {
            printf("httpserv: Failed to launch thread!\n");
            slot->state = rs_idle;
            rv = SECFailure;
            break;
        }

        ++threadCount;
    }
    PZ_Unlock(qLock);

    return rv;
}
Beispiel #10
0
/*
 * check to see if the module has added new slots. PKCS 11 v2.20 allows for
 * modules to add new slots, but never remove them. Slots cannot be added 
 * between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
 * C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
 * grow on the caller. It is permissible for the slots to increase between
 * successive calls with NULL to get the size.
 */
SECStatus
SECMOD_UpdateSlotList(SECMODModule *mod)
{
    CK_RV crv;
    CK_ULONG count;
    CK_ULONG i, oldCount;
    PRBool freeRef = PR_FALSE;
    void *mark = NULL;
    CK_ULONG *slotIDs = NULL;
    PK11SlotInfo **newSlots = NULL;
    PK11SlotInfo **oldSlots = NULL;

    if (!moduleLock) {
    	PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
	return SECFailure;
    }

    /* C_GetSlotList is not a session function, make sure 
     * calls are serialized */
    PZ_Lock(mod->refLock);
    freeRef = PR_TRUE;
    /* see if the number of slots have changed */
    crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError(crv));
	goto loser;
    }
    /* nothing new, blow out early, we want this function to be quick
     * and cheap in the normal case  */
    if (count == mod->slotCount) {
 	PZ_Unlock(mod->refLock);
	return SECSuccess;
    }
    if (count < (CK_ULONG)mod->slotCount) {
	/* shouldn't happen with a properly functioning PKCS #11 module */
	PORT_SetError( SEC_ERROR_INCOMPATIBLE_PKCS11 );
	goto loser;
    }

    /* get the new slot list */
    slotIDs = PORT_NewArray(CK_SLOT_ID, count);
    if (slotIDs == NULL) {
	goto loser;
    }

    crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError(crv));
	goto loser;
    }
    freeRef = PR_FALSE;
    PZ_Unlock(mod->refLock);
    mark = PORT_ArenaMark(mod->arena);
    if (mark == NULL) {
	goto loser;
    }
    newSlots = PORT_ArenaZNewArray(mod->arena,PK11SlotInfo *,count);

    /* walk down the new slot ID list returned from the module. We keep
     * the old slots which match a returned ID, and we initialize the new 
     * slots. */
    for (i=0; i < count; i++) {
	PK11SlotInfo *slot = SECMOD_FindSlotByID(mod,slotIDs[i]);

	if (!slot) {
	    /* we have a new slot create a new slot data structure */
	    slot = PK11_NewSlotInfo(mod);
	    if (!slot) {
		goto loser;
	    }
	    PK11_InitSlot(mod, slotIDs[i], slot);
	    STAN_InitTokenForSlotInfo(NULL, slot);
	}
	newSlots[i] = slot;
    }
    STAN_ResetTokenInterator(NULL);
    PORT_Free(slotIDs);
    slotIDs = NULL;
    PORT_ArenaUnmark(mod->arena, mark);

    /* until this point we're still using the old slot list. Now we update
     * module slot list. We update the slots (array) first then the count, 
     * since we've already guarrenteed that count has increased (just in case 
     * someone is looking at the slots field of  module without holding the 
     * moduleLock */
    SECMOD_GetWriteLock(moduleLock);
    oldCount =mod->slotCount;
    oldSlots = mod->slots;
    mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is
			    * allocated out of the module arena and won't
			    * be freed until the module is freed */
    mod->slotCount = count;
    SECMOD_ReleaseWriteLock(moduleLock);
    /* free our old references before forgetting about oldSlot*/
    for (i=0; i < oldCount; i++) {
	PK11_FreeSlot(oldSlots[i]);
    }
    return SECSuccess;

loser:
    if (freeRef) {
	PZ_Unlock(mod->refLock);
    }
    if (slotIDs) {
	PORT_Free(slotIDs);
    }
    /* free all the slots we allocated. newSlots are part of the
     * mod arena. NOTE: the newSlots array contain both new and old
     * slots, but we kept a reference to the old slots when we built the new
     * array, so we need to free all the slots in newSlots array. */
    if (newSlots) {
	for (i=0; i < count; i++) {
	    if (newSlots[i] == NULL) {
		break; /* hit the last one */
	    }
	    PK11_FreeSlot(newSlots[i]);
	}
    }
    /* must come after freeing newSlots */
    if (mark) {
 	PORT_ArenaRelease(mod->arena, mark);
    }
    return SECFailure;
}
Beispiel #11
0
/*
 * this function waits for a token event on any slot of a given module
 * This function should not be called from more than one thread of the
 * same process (though other threads can make other library calls
 * on this module while this call is blocked).
 */
PK11SlotInfo *
SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
						 PRIntervalTime latency)
{
    CK_SLOT_ID id;
    CK_RV crv;
    PK11SlotInfo *slot;

    if (!pk11_getFinalizeModulesOption() ||
        ((mod->cryptokiVersion.major == 2) &&
         (mod->cryptokiVersion.minor < 1))) { 
        /* if we are sharing the module with other software in our
         * address space, we can't reliably use C_WaitForSlotEvent(),
         * and if the module is version 2.0, C_WaitForSlotEvent() doesn't
         * exist */
	return secmod_HandleWaitForSlotEvent(mod, flags, latency);
    }
    /* first the the PKCS #11 call */
    PZ_Lock(mod->refLock);
    if (mod->evControlMask & SECMOD_END_WAIT) {
	goto end_wait;
    }
    mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT;
    PZ_Unlock(mod->refLock);
    crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL);
    PZ_Lock(mod->refLock);
    mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT;
    /* if we are in end wait, short circuit now, don't even risk
     * going into secmod_HandleWaitForSlotEvent */
    if (mod->evControlMask & SECMOD_END_WAIT) {
	goto end_wait;
    }
    PZ_Unlock(mod->refLock);
    if (crv == CKR_FUNCTION_NOT_SUPPORTED) {
	/* module doesn't support that call, simulate it */
	return secmod_HandleWaitForSlotEvent(mod, flags, latency);
    }
    if (crv != CKR_OK) {
	/* we can get this error if finalize was called while we were
	 * still running. This is the only way to force a C_WaitForSlotEvent()
	 * to return in PKCS #11. In this case, just return that there
	 * was no event. */
	if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
	    PORT_SetError(SEC_ERROR_NO_EVENT);
	} else {
	    PORT_SetError(PK11_MapError(crv));
	}
	return NULL;
    }
    slot = SECMOD_FindSlotByID(mod, id);
    if (slot == NULL) {
	/* possibly a new slot that was added? */
	SECMOD_UpdateSlotList(mod);
	slot = SECMOD_FindSlotByID(mod, id);
    }
    /* if we are in the delay period for the "isPresent" call, reset
     * the delay since we know things have probably changed... */
    if (slot && slot->nssToken && slot->nssToken->slot) {
	nssSlot_ResetDelay(slot->nssToken->slot);
    }
    return slot;

    /* must be called with the lock on. */
end_wait:
    mod->evControlMask &= ~SECMOD_END_WAIT;
    PZ_Unlock(mod->refLock);
    PORT_SetError(SEC_ERROR_NO_EVENT);
    return NULL;
}
Beispiel #12
0
/*
 * pk11_getKeyFromList returns a symKey that has a session (if needSession
 * was specified), or explicitly does not have a session (if needSession
 * was not specified).
 */
static PK11SymKey *
pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) {
    PK11SymKey *symKey = NULL;

    PZ_Lock(slot->freeListLock);
    /* own session list are symkeys with sessions that the symkey owns.
     * 'most' symkeys will own their own session. */
    if (needSession) {
	if (slot->freeSymKeysWithSessionHead) {
    	    symKey = slot->freeSymKeysWithSessionHead;
	    slot->freeSymKeysWithSessionHead = symKey->next;
	    slot->keyCount--;
	}
    }
    /* if we don't need a symkey with its own session, or we couldn't find
     * one on the owner list, get one from the non-owner free list. */
    if (!symKey) {
	if (slot->freeSymKeysHead) {
    	    symKey = slot->freeSymKeysHead;
	    slot->freeSymKeysHead = symKey->next;
	    slot->keyCount--;
	}
    }
    PZ_Unlock(slot->freeListLock);
    if (symKey) {
	symKey->next = NULL;
	if (!needSession) {
	    return symKey;
	}
	/* if we are getting an owner key, make sure we have a valid session.
         * session could be invalid if the token has been removed or because
         * we got it from the non-owner free list */
	if ((symKey->series != slot->series) || 
			 (symKey->session == CK_INVALID_SESSION)) {
	    symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner);
	}
	PORT_Assert(symKey->session != CK_INVALID_SESSION);
	if (symKey->session != CK_INVALID_SESSION)
	    return symKey;
	PK11_FreeSymKey(symKey);
	/* if we are here, we need a session, but couldn't get one, it's 
	 * unlikely we pk11_GetNewSession will succeed if we call it a second
	 * time. */
	return NULL;
    }

    symKey = PORT_New(PK11SymKey);
    if (symKey == NULL) {
	return NULL;
    }

    symKey->next = NULL;
    if (needSession) {
	symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner);
	PORT_Assert(symKey->session != CK_INVALID_SESSION);
        if (symKey->session == CK_INVALID_SESSION) {
	    PK11_FreeSymKey(symKey);
	    symKey = NULL;
	}
    } else {
	symKey->session = CK_INVALID_SESSION;
    }
    return symKey;
}
Beispiel #13
0
static void 
lock_cache(void)
{
    ssl_InitSessionCacheLocks(PR_TRUE);
    PZ_Lock(cacheLock);
}
Beispiel #14
0
static SECStatus
get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen,
                    mp_int *f, mp_int *g)
{
    SECStatus rv = SECSuccess;
    mp_err err = MP_OKAY;
    int cmp;
    PRCList *el;
    struct RSABlindingParamsStr *rsabp = NULL;
    /* Init the list if neccessary (the init function is only called once!) */
    if (blindingParamsList.lock == NULL) {
	if (PR_CallOnce(&coBPInit, init_blinding_params_list) != PR_SUCCESS) {
	    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
	    return SECFailure;
	}
    }
    /* Acquire the list lock */
    PZ_Lock(blindingParamsList.lock);
    /* Walk the list looking for the private key */
    for (el = PR_NEXT_LINK(&blindingParamsList.head);
         el != &blindingParamsList.head;
         el = PR_NEXT_LINK(el)) {
	rsabp = (struct RSABlindingParamsStr *)el;
	cmp = SECITEM_CompareItem(&rsabp->modulus, &key->modulus);
	if (cmp == 0) {
	    /* Check the usage counter for the parameters */
	    if (--rsabp->counter <= 0) {
		/* Regenerate the blinding parameters */
		CHECK_SEC_OK( generate_blinding_params(rsabp, key, n, modLen) );
	    }
	    /* Return the parameters */
	    CHECK_MPI_OK( mp_copy(&rsabp->f, f) );
	    CHECK_MPI_OK( mp_copy(&rsabp->g, g) );
	    /* Now that the params are located, release the list lock. */
	    PZ_Unlock(blindingParamsList.lock); /* XXX when fails? */
	    return SECSuccess;
	} else if (cmp > 0) {
	    /* The key is not in the list.  Break to param creation. */
	    break;
	}
    }
    /* At this point, the key is not in the list.  el should point to the
    ** list element that this key should be inserted before.  NOTE: the list
    ** lock is still held, so there cannot be a race condition here.
    */
    rsabp = (struct RSABlindingParamsStr *)
              PORT_ZAlloc(sizeof(struct RSABlindingParamsStr));
    if (!rsabp) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	goto cleanup;
    }
    /* Initialize the list pointer for the element */
    PR_INIT_CLIST(&rsabp->link);
    /* Initialize the blinding parameters 
    ** This ties up the list lock while doing some heavy, element-specific
    ** operations, but we don't want to insert the element until it is valid,
    ** which requires computing the blinding params.  If this proves costly,
    ** it could be done after the list lock is released, and then if it fails
    ** the lock would have to be reobtained and the invalid element removed.
    */
    rv = init_blinding_params(rsabp, key, n, modLen);
    if (rv != SECSuccess) {
	PORT_ZFree(rsabp, sizeof(struct RSABlindingParamsStr));
	goto cleanup;
    }
    /* Insert the new element into the list
    ** If inserting in the middle of the list, el points to the link
    ** to insert before.  Otherwise, the link needs to be appended to
    ** the end of the list, which is the same as inserting before the
    ** head (since el would have looped back to the head).
    */
    PR_INSERT_BEFORE(&rsabp->link, el);
    /* Return the parameters */
    CHECK_MPI_OK( mp_copy(&rsabp->f, f) );
    CHECK_MPI_OK( mp_copy(&rsabp->g, g) );
    /* Release the list lock */
    PZ_Unlock(blindingParamsList.lock); /* XXX when fails? */
    return SECSuccess;
cleanup:
    /* It is possible to reach this after the lock is already released.
    ** Ignore the error in that case.
    */
    PZ_Unlock(blindingParamsList.lock);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    return SECFailure;
}
Beispiel #15
0
/*
** Generate some random bytes, using the global random number generator
** object.
*/
static SECStatus 
prng_GenerateGlobalRandomBytes(RNGContext *rng,
                               void *dest, size_t len)
{
    SECStatus rv = SECSuccess;
    PRUint8 *output = dest;
    /* check for a valid global RNG context */
    PORT_Assert(rng != NULL);
    if (rng == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    /* FIPS limits the amount of entropy available in a single request */
    if (len > PRNG_MAX_REQUEST_SIZE) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    /* --- LOCKED --- */
    PZ_Lock(rng->lock);
    /* Check the amount of seed data in the generator.  If not enough,
     * don't produce any data.
     */
    if (rng->reseed_counter[0] >= RESEED_VALUE) {
	rv = prng_reseed_test(rng, NULL, 0, NULL, 0);
	PZ_Unlock(rng->lock);
	if (rv != SECSuccess) {
	    return rv;
	}
	RNG_SystemInfoForRNG();
	PZ_Lock(rng->lock);
    }
    /*
     * see if we have enough bytes to fulfill the request.
     */
    if (len <= rng->dataAvail) {
	memcpy(output, rng->data + ((sizeof rng->data) - rng->dataAvail), len);
	memset(rng->data + ((sizeof rng->data) - rng->dataAvail), 0, len);
	rng->dataAvail -= len;
	rv = SECSuccess;
    /* if we are asking for a small number of bytes, cache the rest of 
     * the bytes */
    } else if (len < sizeof rng->data) {
	rv = prng_generateNewBytes(rng, rng->data, sizeof rng->data, 
			rng->additionalAvail ? rng->additionalDataCache : NULL,
			rng->additionalAvail);
	rng->additionalAvail = 0;
	if (rv == SECSuccess) {
	    memcpy(output, rng->data, len);
	    memset(rng->data, 0, len); 
	    rng->dataAvail = (sizeof rng->data) - len;
	}
    /* we are asking for lots of bytes, just ask the generator to pass them */
    } else {
	rv = prng_generateNewBytes(rng, output, len,
			rng->additionalAvail ? rng->additionalDataCache : NULL,
			rng->additionalAvail);
	rng->additionalAvail = 0;
    }
    PZ_Unlock(rng->lock);
    /* --- UNLOCKED --- */
    return rv;
}
Beispiel #16
0
static SECStatus
get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen,
                    mp_int *f, mp_int *g)
{
    RSABlindingParams *rsabp           = NULL;
    blindingParams    *bpUnlinked      = NULL;
    blindingParams    *bp, *prevbp     = NULL;
    PRCList           *el;
    SECStatus          rv              = SECSuccess;
    mp_err             err             = MP_OKAY;
    int                cmp             = -1;
    PRBool             holdingLock     = PR_FALSE;

    do {
	if (blindingParamsList.lock == NULL) {
	    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
	    return SECFailure;
	}
	/* Acquire the list lock */
	PZ_Lock(blindingParamsList.lock);
	holdingLock = PR_TRUE;

	/* Walk the list looking for the private key */
	for (el = PR_NEXT_LINK(&blindingParamsList.head);
	     el != &blindingParamsList.head;
	     el = PR_NEXT_LINK(el)) {
	    rsabp = (RSABlindingParams *)el;
	    cmp = SECITEM_CompareItem(&rsabp->modulus, &key->modulus);
	    if (cmp >= 0) {
		/* The key is found or not in the list. */
		break;
	    }
	}

	if (cmp) {
	    /* At this point, the key is not in the list.  el should point to 
	    ** the list element before which this key should be inserted. 
	    */
	    rsabp = PORT_ZNew(RSABlindingParams);
	    if (!rsabp) {
		PORT_SetError(SEC_ERROR_NO_MEMORY);
		goto cleanup;
	    }

	    rv = init_blinding_params(rsabp, key, n, modLen);
	    if (rv != SECSuccess) {
		PORT_ZFree(rsabp, sizeof(RSABlindingParams));
		goto cleanup;
	    }

	    /* Insert the new element into the list
	    ** If inserting in the middle of the list, el points to the link
	    ** to insert before.  Otherwise, the link needs to be appended to
	    ** the end of the list, which is the same as inserting before the
	    ** head (since el would have looped back to the head).
	    */
	    PR_INSERT_BEFORE(&rsabp->link, el);
	}

	/* We've found (or created) the RSAblindingParams struct for this key.
	 * Now, search its list of ready blinding params for a usable one.
	 */
	while (0 != (bp = rsabp->bp)) {
	    if (--(bp->counter) > 0) {
		/* Found a match and there are still remaining uses left */
		/* Return the parameters */
		CHECK_MPI_OK( mp_copy(&bp->f, f) );
		CHECK_MPI_OK( mp_copy(&bp->g, g) );

		PZ_Unlock(blindingParamsList.lock); 
		return SECSuccess;
	    }
	    /* exhausted this one, give its values to caller, and
	     * then retire it.
	     */
	    mp_exch(&bp->f, f);
	    mp_exch(&bp->g, g);
	    mp_clear( &bp->f );
	    mp_clear( &bp->g );
	    bp->counter = 0;
	    /* Move to free list */
	    rsabp->bp   = bp->next;
	    bp->next    = rsabp->free;
	    rsabp->free = bp;
	    /* In case there're threads waiting for new blinding
	     * value - notify 1 thread the value is ready
	     */
	    if (blindingParamsList.waitCount > 0) {
		PR_NotifyCondVar( blindingParamsList.cVar );
		blindingParamsList.waitCount--;
	    }
	    PZ_Unlock(blindingParamsList.lock); 
	    return SECSuccess;
	}
	/* We did not find a usable set of blinding params.  Can we make one? */
	/* Find a free bp struct. */
	prevbp = NULL;
	if ((bp = rsabp->free) != NULL) {
	    /* unlink this bp */
	    rsabp->free  = bp->next;
	    bp->next     = NULL;
	    bpUnlinked   = bp;  /* In case we fail */

	    PZ_Unlock(blindingParamsList.lock); 
	    holdingLock = PR_FALSE;
	    /* generate blinding parameter values for the current thread */
	    CHECK_SEC_OK( generate_blinding_params(key, f, g, n, modLen ) );

	    /* put the blinding parameter values into cache */
	    CHECK_MPI_OK( mp_init( &bp->f) );
	    CHECK_MPI_OK( mp_init( &bp->g) );
	    CHECK_MPI_OK( mp_copy( f, &bp->f) );
	    CHECK_MPI_OK( mp_copy( g, &bp->g) );

	    /* Put this at head of queue of usable params. */
	    PZ_Lock(blindingParamsList.lock);
	    holdingLock = PR_TRUE;
	    /* initialize RSABlindingParamsStr */
	    bp->counter = RSA_BLINDING_PARAMS_MAX_REUSE;
	    bp->next    = rsabp->bp;
	    rsabp->bp   = bp;
	    bpUnlinked  = NULL;
	    /* In case there're threads waiting for new blinding value
	     * just notify them the value is ready
	     */
	    if (blindingParamsList.waitCount > 0) {
		PR_NotifyAllCondVar( blindingParamsList.cVar );
		blindingParamsList.waitCount = 0;
	    }
	    PZ_Unlock(blindingParamsList.lock);
	    return SECSuccess;
	}
	/* Here, there are no usable blinding parameters available,
	 * and no free bp blocks, presumably because they're all 
	 * actively having parameters generated for them.
	 * So, we need to wait here and not eat up CPU until some 
	 * change happens. 
	 */
	blindingParamsList.waitCount++;
	PR_WaitCondVar( blindingParamsList.cVar, PR_INTERVAL_NO_TIMEOUT );
	PZ_Unlock(blindingParamsList.lock); 
	holdingLock = PR_FALSE;
    } while (1);

cleanup:
    /* It is possible to reach this after the lock is already released.  */
    if (bpUnlinked) {
	if (!holdingLock) {
	    PZ_Lock(blindingParamsList.lock);
	    holdingLock = PR_TRUE;
	}
	bp = bpUnlinked;
	mp_clear( &bp->f );
	mp_clear( &bp->g );
	bp->counter = 0;
    	/* Must put the unlinked bp back on the free list */
	bp->next    = rsabp->free;
	rsabp->free = bp;
    }
    if (holdingLock) {
	PZ_Unlock(blindingParamsList.lock);
	holdingLock = PR_FALSE;
    }
    if (err) {
	MP_TO_SEC_ERROR(err);
    }
    return SECFailure;
}
Beispiel #17
0
SECStatus
do_accepts(
    PRFileDesc *listen_sock,
    PRFileDesc *model_sock,
    int         requestCert
    )
{
    PRNetAddr   addr;
    PRErrorCode  perr;
#ifdef XP_UNIX
    struct sigaction act;
#endif

    VLOG(("selfserv: do_accepts: starting"));
    PR_SetThreadPriority( PR_GetCurrentThread(), PR_PRIORITY_HIGH);

    acceptorThread = PR_GetCurrentThread();
#ifdef XP_UNIX
    /* set up the signal handler */
    act.sa_handler = sigusr1_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (sigaction(SIGUSR1, &act, NULL)) {
        fprintf(stderr, "Error installing signal handler.\n");
        exit(1);
    }
#endif
    while (!stopping) {
	PRFileDesc *tcp_sock;
	PRCList    *myLink;

	FPRINTF(stderr, "\n\n\nselfserv: About to call accept.\n");
	tcp_sock = PR_Accept(listen_sock, &addr, PR_INTERVAL_NO_TIMEOUT);
	if (tcp_sock == NULL) {
    	    perr      = PR_GetError();
	    if ((perr != PR_CONNECT_RESET_ERROR &&
	         perr != PR_PENDING_INTERRUPT_ERROR) || verbose) {
		errWarn("PR_Accept");
	    } 
	    if (perr == PR_CONNECT_RESET_ERROR) {
		FPRINTF(stderr, 
		        "Ignoring PR_CONNECT_RESET_ERROR error - continue\n");
		continue;
	    }
	    stopping = 1;
	    break;
	}

        VLOG(("selfserv: do_accept: Got connection\n"));

	PZ_Lock(qLock);
	while (PR_CLIST_IS_EMPTY(&freeJobs) && !stopping) {
            PZ_WaitCondVar(freeListNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
	}
	if (stopping) {
	    PZ_Unlock(qLock);
            if (tcp_sock) {
	        PR_Close(tcp_sock);
            }
	    break;
	}
	myLink = PR_LIST_HEAD(&freeJobs);
	PR_REMOVE_AND_INIT_LINK(myLink);
	/* could release qLock here and reacquire it 7 lines below, but 
	** why bother for 4 assignment statements? 
	*/
	{
	    JOB * myJob = (JOB *)myLink;
	    myJob->tcp_sock    = tcp_sock;
	    myJob->model_sock  = model_sock;
	    myJob->requestCert = requestCert;
	}

	PR_APPEND_LINK(myLink, &jobQ);
	PZ_NotifyCondVar(jobQNotEmptyCv);
	PZ_Unlock(qLock);
    }

    FPRINTF(stderr, "selfserv: Closing listen socket.\n");
    VLOG(("selfserv: do_accepts: exiting"));
    if (listen_sock) {
        PR_Close(listen_sock);
    }
    return SECSuccess;
}
Beispiel #18
0
/*
 * destroy a symetric key
 */
void
PK11_FreeSymKey(PK11SymKey *symKey)
{
    PK11SlotInfo *slot;
    PRBool freeit = PR_TRUE;

    if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) {
	PK11SymKey *parent = symKey->parent;

	symKey->parent = NULL;
	if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) {
	    pk11_EnterKeyMonitor(symKey);
	    (void) PK11_GETTAB(symKey->slot)->
		C_DestroyObject(symKey->session, symKey->objectID);
	    pk11_ExitKeyMonitor(symKey);
	}
	if (symKey->data.data) {
	    PORT_Memset(symKey->data.data, 0, symKey->data.len);
	    PORT_Free(symKey->data.data);
	}
	/* free any existing data */
	if (symKey->userData && symKey->freeFunc) {
	    (*symKey->freeFunc)(symKey->userData);
	}
        slot = symKey->slot;
        PZ_Lock(slot->freeListLock);
	if (slot->keyCount < slot->maxKeyCount) {
	    /* 
             * freeSymkeysWithSessionHead contain a list of reusable
	     *  SymKey structures with valid sessions.
	     *    sessionOwner must be true.
             *    session must be valid.
             * freeSymKeysHead contain a list of SymKey structures without
             *  valid session.
             *    session must be CK_INVALID_SESSION.
	     *    though sessionOwner is false, callers should not depend on
	     *    this fact.
	     */
	    if (symKey->sessionOwner) {
		PORT_Assert (symKey->session != CK_INVALID_SESSION);
		symKey->next = slot->freeSymKeysWithSessionHead;
		slot->freeSymKeysWithSessionHead = symKey;
	    } else {
		symKey->session = CK_INVALID_SESSION;
		symKey->next = slot->freeSymKeysHead;
		slot->freeSymKeysHead = symKey;
	    }
	    slot->keyCount++;
	    symKey->slot = NULL;
	    freeit = PR_FALSE;
        }
	PZ_Unlock(slot->freeListLock);
        if (freeit) {
	    pk11_CloseSession(symKey->slot, symKey->session,
							symKey->sessionOwner);
	    PORT_Free(symKey);
	}
	PK11_FreeSlot(slot);

	if (parent) {
	    PK11_FreeSymKey(parent);
	}
    }
}
Beispiel #19
0
NSS_IMPLEMENT void
nssTrustDomain_LockCertCache(NSSTrustDomain *td)
{
    PZ_Lock(td->cache->lock);
}
Beispiel #20
0
CK_RV PR_CALLBACK
secmodLockMutext(CK_VOID_PTR mutext)
{
    PZ_Lock((PZLock *)mutext);
    return CKR_OK;
}
Beispiel #21
0
/*
 * this handles modules that do not support C_WaitForSlotEvent().
 * The internal flags are stored. Note that C_WaitForSlotEvent() does not
 * have a timeout, so we don't have one for handleWaitForSlotEvent() either.
 */
PK11SlotInfo *
secmod_HandleWaitForSlotEvent(SECMODModule *mod,  unsigned long flags,
						PRIntervalTime latency)
{
    PRBool removableSlotsFound = PR_FALSE;
    int i;
    int error = SEC_ERROR_NO_EVENT;

    if (!moduleLock) {
    	PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
	return NULL;
    }
    PZ_Lock(mod->refLock);
    if (mod->evControlMask & SECMOD_END_WAIT) {
	mod->evControlMask &= ~SECMOD_END_WAIT;
	PZ_Unlock(mod->refLock);
	PORT_SetError(SEC_ERROR_NO_EVENT);
	return NULL;
    }
    mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT;
    while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) {
	PZ_Unlock(mod->refLock);
	/* now is a good time to see if new slots have been added */
	SECMOD_UpdateSlotList(mod);

	/* loop through all the slots on a module */
	SECMOD_GetReadLock(moduleLock);
	for (i=0; i < mod->slotCount; i++) {
	    PK11SlotInfo *slot = mod->slots[i];
	    PRUint16 series;
	    PRBool present;

	    /* perm modules do not change */
	    if (slot->isPerm) {
		continue;
	    }
	    removableSlotsFound = PR_TRUE;
	    /* simulate the PKCS #11 module flags. are the flags different
	     * from the last time we called? */
	    series = slot->series;
	    present = PK11_IsPresent(slot);
	    if ((slot->flagSeries != series) || (slot->flagState != present)) {
		slot->flagState = present;
		slot->flagSeries = series;
		SECMOD_ReleaseReadLock(moduleLock);
		PZ_Lock(mod->refLock);
		mod->evControlMask &= ~SECMOD_END_WAIT;
		PZ_Unlock(mod->refLock);
		return PK11_ReferenceSlot(slot);
	    }
	}
	SECMOD_ReleaseReadLock(moduleLock);
	/* if everything was perm modules, don't lock up forever */
	if ((mod->slotCount !=0) && !removableSlotsFound) {
	    error =SEC_ERROR_NO_SLOT_SELECTED;
	    PZ_Lock(mod->refLock);
	    break;
	}
	if (flags & CKF_DONT_BLOCK) {
	    PZ_Lock(mod->refLock);
	    break;
	}
	PR_Sleep(latency);
 	PZ_Lock(mod->refLock);
    }
    mod->evControlMask &= ~SECMOD_END_WAIT;
    PZ_Unlock(mod->refLock);
    PORT_SetError(error);
    return NULL;
}