Example #1
0
/*
 *  Return the final digested or signed data...
 *  this routine can either take pre initialized data, or allocate data
 *  either out of an arena or out of the standard heap.
 */
SECStatus
PK11_DigestFinal(PK11Context *context,unsigned char *data,
                 unsigned int *outLen, unsigned int length)
{
    CK_ULONG len;
    CK_RV crv;
    SECStatus rv;


    /* if we ran out of session, we need to restore our previously stored
     * state.
     */
    PK11_EnterContextMonitor(context);
    if (!context->ownSession) {
        rv = pk11_restoreContext(context,context->savedData,
                                 context->savedLength);
        if (rv != SECSuccess) {
            PK11_ExitContextMonitor(context);
            return rv;
        }
    }

    len = length;
    switch (context->operation) {
    case CKA_SIGN:
        crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
                data,&len);
        break;
    case CKA_VERIFY:
        crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
                data,len);
        break;
    case CKA_DIGEST:
        crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
                data,&len);
        break;
    case CKA_ENCRYPT:
        crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
                data, &len);
        break;
    case CKA_DECRYPT:
        crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
                data, &len);
        break;
    default:
        crv = CKR_OPERATION_NOT_INITIALIZED;
        break;
    }
    PK11_ExitContextMonitor(context);

    *outLen = (unsigned int) len;
    context->init = PR_FALSE; /* allow Begin to start up again */


    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
        return SECFailure;
    }
    return SECSuccess;
}
Example #2
0
/*
 * Change an existing user password
 */
SECStatus
PK11_ChangePW(PK11SlotInfo *slot, const char *oldpw, const char *newpw)
{
    CK_RV crv;
    SECStatus rv = SECFailure;
    int newLen;
    int oldLen;
    CK_SESSION_HANDLE rwsession;

    if (newpw == NULL) newpw = "";
    if (oldpw == NULL) oldpw = "";
    newLen = PORT_Strlen(newpw);
    oldLen = PORT_Strlen(oldpw);

    /* get a rwsession */
    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
    	PORT_SetError(SEC_ERROR_BAD_DATA);
    	return rv;
    }

    crv = PK11_GETTAB(slot)->C_SetPIN(rwsession,
		(unsigned char *)oldpw,oldLen,(unsigned char *)newpw,newLen);
    if (crv == CKR_OK) {
	rv = SECSuccess;
    } else {
	PORT_SetError(PK11_MapError(crv));
    }

    PK11_RestoreROSession(slot,rwsession);

    /* update our view of the world */
    PK11_InitToken(slot,PR_TRUE);
    return rv;
}
Example #3
0
/*
 * save the current context. Allocate Space if necessary.
 */
static unsigned char *
pk11_saveContextHelper(PK11Context *context, unsigned char *buffer,
                       unsigned long *savedLength)
{
    CK_RV crv;

    /* If buffer is NULL, this will get the length */
    crv = PK11_GETTAB(context->slot)->C_GetOperationState(context->session,
            (CK_BYTE_PTR)buffer,
            savedLength);
    if (!buffer || (crv == CKR_BUFFER_TOO_SMALL)) {
        /* the given buffer wasn't big enough (or was NULL), but we
         * have the length, so try again with a new buffer and the
         * correct length
         */
        unsigned long bufLen = *savedLength;
        buffer = PORT_Alloc(bufLen);
        if (buffer == NULL) {
            return (unsigned char *)NULL;
        }
        crv = PK11_GETTAB(context->slot)->C_GetOperationState(
                  context->session,
                  (CK_BYTE_PTR)buffer,
                  savedLength);
        if (crv != CKR_OK) {
            PORT_ZFree(buffer, bufLen);
        }
    }
    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
        return (unsigned char *)NULL;
    }
    return buffer;
}
Example #4
0
/*
 * Context initialization. Used by all flavors of CreateContext
 */
static SECStatus
pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info)
{
    CK_RV crv;
    PK11SymKey *symKey = context->key;
    SECStatus rv = SECSuccess;

    switch (context->operation) {
    case CKA_ENCRYPT:
        crv=PK11_GETTAB(context->slot)->C_EncryptInit(context->session,
                mech_info, symKey->objectID);
        break;
    case CKA_DECRYPT:
        if (context->fortezzaHack) {
            CK_ULONG count = 0;;
            /* generate the IV for fortezza */
            crv=PK11_GETTAB(context->slot)->C_EncryptInit(context->session,
                    mech_info, symKey->objectID);
            if (crv != CKR_OK) break;
            PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
                    NULL, &count);
        }
        crv=PK11_GETTAB(context->slot)->C_DecryptInit(context->session,
                mech_info, symKey->objectID);
        break;
    case CKA_SIGN:
        crv=PK11_GETTAB(context->slot)->C_SignInit(context->session,
                mech_info, symKey->objectID);
        break;
    case CKA_VERIFY:
        crv=PK11_GETTAB(context->slot)->C_SignInit(context->session,
                mech_info, symKey->objectID);
        break;
    case CKA_DIGEST:
        crv=PK11_GETTAB(context->slot)->C_DigestInit(context->session,
                mech_info);
        break;
    default:
        crv = CKR_OPERATION_NOT_INITIALIZED;
        break;
    }

    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
        return SECFailure;
    }

    /*
     * handle session starvation case.. use our last session to multiplex
     */
    if (!context->ownSession) {
        context->savedData = pk11_saveContext(context,context->savedData,
                                              &context->savedLength);
        if (context->savedData == NULL) rv = SECFailure;
        /* clear out out session for others to use */
        pk11_Finalize(context);
    }
    return rv;
}
Example #5
0
/*
 * Check the user's password. Logout before hand to make sure that
 * we are really checking the password.
 */
SECStatus
PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw)
{
    int len = 0;
    CK_RV crv;
    SECStatus rv;
    int64 currtime = PR_Now();

    if (slot->protectedAuthPath) {
	len = 0;
	pw = NULL;
    } else if (pw == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    } else {
	len = PORT_Strlen(pw);
    }

    /*
     * If the token does't need a login, don't try to relogin beause the
     * effect is undefined. It's not clear what it means to check a non-empty
     * password with such a token, so treat that as an error.
     */
    if (!slot->needLogin) {
        if (len == 0) {
            rv = SECSuccess;
        } else {
            PORT_SetError(SEC_ERROR_BAD_PASSWORD);
            rv = SECFailure;
        }
        return rv;
    }

    /* force a logout */
    PK11_EnterSlotMonitor(slot);
    PK11_GETTAB(slot)->C_Logout(slot->session);

    crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
					(unsigned char *)pw,len);
    slot->lastLoginCheck = 0;
    PK11_ExitSlotMonitor(slot);
    switch (crv) {
    /* if we're already logged in, we're good to go */
    case CKR_OK:
	slot->authTransact = PK11_Global.transaction;
	slot->authTime = currtime;
	rv = SECSuccess;
	break;
    case CKR_PIN_INCORRECT:
	PORT_SetError(SEC_ERROR_BAD_PASSWORD);
	rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
	break;
    default:
	PORT_SetError(PK11_MapError(crv));
	rv = SECFailure; /* some failure we can't fix by retrying */
    }
    return rv;
}
Example #6
0
SECStatus
PK11_GetModInfo(SECMODModule *mod,CK_INFO *info)
{
    CK_RV crv;

    if (mod->functionList == NULL) return SECFailure;
    crv = PK11_GETTAB(mod)->C_GetInfo(info);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError(crv));
    }	
    return (crv == CKR_OK) ? SECSuccess : SECFailure;
}
Example #7
0
/*
 * copy a template of attributes from a source object to a target object.
 * if target object is not given, create it.
 */
static SECStatus
pk11_copyAttributes(PLArenaPool *arena,
                    PK11SlotInfo *targetSlot, CK_OBJECT_HANDLE targetID,
                    PK11SlotInfo *sourceSlot, CK_OBJECT_HANDLE sourceID,
                    CK_ATTRIBUTE *copyTemplate, CK_ULONG copyTemplateCount)
{
    SECStatus rv;
    CK_ATTRIBUTE *newTemplate = NULL;
    CK_RV crv;

    crv = PK11_GetAttributes(arena, sourceSlot, sourceID,
                             copyTemplate, copyTemplateCount);
    /* if we have missing attributes, just skip them and create the object */
    if (crv == CKR_ATTRIBUTE_TYPE_INVALID) {
        CK_ULONG i, j;
        newTemplate = PORT_NewArray(CK_ATTRIBUTE, copyTemplateCount);
        if (!newTemplate) {
            return SECFailure;
        }
        /* remove the unknown attributes. If we don't have enough attributes
	 * PK11_CreateNewObject() will fail */
        for (i = 0, j = 0; i < copyTemplateCount; i++) {
            if (copyTemplate[i].ulValueLen != -1) {
                newTemplate[j] = copyTemplate[i];
                j++;
            }
        }
        copyTemplate = newTemplate;
        copyTemplateCount = j;
        crv = PK11_GetAttributes(arena, sourceSlot, sourceID,
                                 copyTemplate, copyTemplateCount);
    }
    if (crv != CKR_OK) {
        PORT_SetError(PK11_MapError(crv));
        return SECFailure;
    }
    if (targetID == CK_INVALID_HANDLE) {
        /* we need to create the object */
        rv = PK11_CreateNewObject(targetSlot, CK_INVALID_SESSION,
                                  copyTemplate, copyTemplateCount, PR_TRUE, &targetID);
    } else {
        /* update the existing object with the new attributes */
        rv = pk11_setAttributes(targetSlot, targetID,
                                copyTemplate, copyTemplateCount);
    }
    if (newTemplate) {
        free(newTemplate);
    }
    return rv;
}
Example #8
0
/*
 * NOTE: this assumes that we are logged out of the card before hand
 */
SECStatus
PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw)
{
    CK_SESSION_HANDLE rwsession;
    CK_RV crv;
    SECStatus rv = SECFailure;
    int len = 0;

    /* get a rwsession */
    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
    	PORT_SetError(SEC_ERROR_BAD_DATA);
    	return rv;
    }

    if (slot->protectedAuthPath) {
	len = 0;
	ssopw = NULL;
    } else if (ssopw == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    } else {
	len = PORT_Strlen(ssopw);
    }

    /* check the password */
    crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO,
						(unsigned char *)ssopw,len);
    slot->lastLoginCheck = 0;
    switch (crv) {
    /* if we're already logged in, we're good to go */
    case CKR_OK:
	rv = SECSuccess;
	break;
    case CKR_PIN_INCORRECT:
	PORT_SetError(SEC_ERROR_BAD_PASSWORD);
	rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
	break;
    default:
	PORT_SetError(PK11_MapError(crv));
	rv = SECFailure; /* some failure we can't fix by retrying */
    }
    PK11_GETTAB(slot)->C_Logout(rwsession);
    slot->lastLoginCheck = 0;

    /* release rwsession */
    PK11_RestoreROSession(slot,rwsession);
    return rv;
}
Example #9
0
SECStatus
PK11_Logout(PK11SlotInfo *slot)
{
    CK_RV crv;

    /* force a logout */
    PK11_EnterSlotMonitor(slot);
    crv = PK11_GETTAB(slot)->C_Logout(slot->session);
    slot->lastLoginCheck = 0;
    PK11_ExitSlotMonitor(slot);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError(crv));
	return SECFailure;
    }
    return  SECSuccess;
}
Example #10
0
/*
 * restore the current context
 */
SECStatus
pk11_restoreContext(PK11Context *context, void *space, unsigned long savedLength)
{
    CK_RV crv;
    CK_OBJECT_HANDLE objectID = (context->key) ? context->key->objectID : CK_INVALID_HANDLE;

    PORT_Assert(space != NULL);
    if (space == NULL) {
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
        return SECFailure;
    }
    crv = PK11_GETTAB(context->slot)->C_SetOperationState(context->session, (CK_BYTE_PTR)space, savedLength, objectID, 0);
    if (crv != CKR_OK) {
        PORT_SetError(PK11_MapError(crv));
        return SECFailure;
    }
    return SECSuccess;
}
Example #11
0
/*
 * This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic
 * function, possibly bringing down the pkcs #11 module in question. This
 * should be OK because 1) it does reinitialize, and 2) it should only be
 * called when we are on our way to tear the whole system down anyway.
 */
SECStatus
SECMOD_CancelWait(SECMODModule *mod)
{
    unsigned long controlMask;
    SECStatus rv = SECSuccess;
    CK_RV crv;

    PZ_Lock(mod->refLock);
    mod->evControlMask |= SECMOD_END_WAIT;
    controlMask = mod->evControlMask;
    if (controlMask & SECMOD_WAIT_PKCS11_EVENT) {
        if (!pk11_getFinalizeModulesOption()) {
            /* can't get here unless pk11_getFinalizeModulesOption is set */
            PORT_Assert(0);
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
            rv = SECFailure;
            goto loser;
        }
	/* NOTE: this call will drop all transient keys, in progress
	 * operations, and any authentication. This is the only documented
	 * way to get WaitForSlotEvent to return. Also note: for non-thread
	 * safe tokens, we need to hold the module lock, this is not yet at
	 * system shutdown/startup time, so we need to protect these calls */
	crv = PK11_GETTAB(mod)->C_Finalize(NULL);
	/* ok, we slammed the module down, now we need to reinit it in case
	 * we intend to use it again */
	if (CKR_OK == crv) {
            PRBool alreadyLoaded;
	    secmod_ModuleInit(mod, NULL, &alreadyLoaded);
	} else {
	    /* Finalized failed for some reason,  notify the application
	     * so maybe it has a prayer of recovering... */
	    PORT_SetError(PK11_MapError(crv));
	    rv = SECFailure;
	}
    } else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) {
	mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT; 
				/* Simulated events will eventually timeout
				 * and wake up in the loop */
    }
loser:
    PZ_Unlock(mod->refLock);
    return rv;
}
Example #12
0
/*
 * Check the user's password. Logout before hand to make sure that
 * we are really checking the password.
 */
SECStatus
PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw)
{
    int len = 0;
    CK_RV crv;
    SECStatus rv;
    int64 currtime = PR_Now();

    if (slot->protectedAuthPath) {
	len = 0;
	pw = NULL;
    } else if (pw == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    } else {
	len = PORT_Strlen(pw);
    }

    /* force a logout */
    PK11_EnterSlotMonitor(slot);
    PK11_GETTAB(slot)->C_Logout(slot->session);

    crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
					(unsigned char *)pw,len);
    slot->lastLoginCheck = 0;
    PK11_ExitSlotMonitor(slot);
    switch (crv) {
    /* if we're already logged in, we're good to go */
    case CKR_OK:
	slot->authTransact = PK11_Global.transaction;
	slot->authTime = currtime;
	rv = SECSuccess;
	break;
    case CKR_PIN_INCORRECT:
	PORT_SetError(SEC_ERROR_BAD_PASSWORD);
	rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
	break;
    default:
	PORT_SetError(PK11_MapError(crv));
	rv = SECFailure; /* some failure we can't fix by retrying */
    }
    return rv;
}
/*
 * write a bunch of attributes out to an existing object.
 */
static SECStatus
pk11_setAttributes(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
		CK_ATTRIBUTE *setTemplate, CK_ULONG setTemplCount)
{
    CK_RV crv;
    CK_SESSION_HANDLE rwsession;

    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
    	PORT_SetError(SEC_ERROR_BAD_DATA);
    	return SECFailure;
    }
    crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, id,
			setTemplate, setTemplCount);
    PK11_RestoreROSession(slot, rwsession);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError(crv));
	return SECFailure;
    }
    return SECSuccess;
}
Example #14
0
/*
 * execute a digest/signature operation
 */
SECStatus
PK11_DigestOp(PK11Context *context, const unsigned char * in, unsigned inLen)
{
    CK_RV crv = CKR_OK;
    SECStatus rv = SECSuccess;

    if (!in) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /* if we ran out of session, we need to restore our previously stored
     * state.
     */
    context->init = PR_FALSE;
    PK11_EnterContextMonitor(context);
    if (!context->ownSession) {
        rv = pk11_restoreContext(context,context->savedData,
                                 context->savedLength);
        if (rv != SECSuccess) {
            PK11_ExitContextMonitor(context);
            return rv;
        }
    }

    switch (context->operation) {
    /* also for MAC'ing */
    case CKA_SIGN:
        crv=PK11_GETTAB(context->slot)->C_SignUpdate(context->session,
                (unsigned char *)in,
                inLen);
        break;
    case CKA_VERIFY:
        crv=PK11_GETTAB(context->slot)->C_VerifyUpdate(context->session,
                (unsigned char *)in,
                inLen);
        break;
    case CKA_DIGEST:
        crv=PK11_GETTAB(context->slot)->C_DigestUpdate(context->session,
                (unsigned char *)in,
                inLen);
        break;
    default:
        crv = CKR_OPERATION_NOT_INITIALIZED;
        break;
    }

    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
        rv = SECFailure;
    }

    /*
     * handle session starvation case.. use our last session to multiplex
     */
    if (!context->ownSession) {
        context->savedData = pk11_saveContext(context,context->savedData,
                                              &context->savedLength);
        if (context->savedData == NULL) rv = SECFailure;

        /* clear out out session for others to use */
        pk11_Finalize(context);
    }
    PK11_ExitContextMonitor(context);
    return rv;
}
Example #15
0
/*
 * execute a bulk encryption operation
 */
SECStatus
PK11_CipherOp(PK11Context *context, unsigned char * out, int *outlen,
              int maxout, unsigned char *in, int inlen)
{
    CK_RV crv = CKR_OK;
    CK_ULONG length = maxout;
    CK_ULONG offset =0;
    SECStatus rv = SECSuccess;
    unsigned char *saveOut = out;
    unsigned char *allocOut = NULL;

    /* if we ran out of session, we need to restore our previously stored
     * state.
     */
    PK11_EnterContextMonitor(context);
    if (!context->ownSession) {
        rv = pk11_restoreContext(context,context->savedData,
                                 context->savedLength);
        if (rv != SECSuccess) {
            PK11_ExitContextMonitor(context);
            return rv;
        }
    }

    /*
     * The fortezza hack is to send 8 extra bytes on the first encrypted and
     * loose them on the first decrypt.
     */
    if (context->fortezzaHack) {
        unsigned char random[8];
        if (context->operation == CKA_ENCRYPT) {
            PK11_ExitContextMonitor(context);
            rv = PK11_GenerateRandom(random,sizeof(random));
            PK11_EnterContextMonitor(context);

            /* since we are offseting the output, we can't encrypt back into
             * the same buffer... allocate a temporary buffer just for this
             * call. */
            allocOut = out = (unsigned char*)PORT_Alloc(maxout);
            if (out == NULL) {
                PK11_ExitContextMonitor(context);
                return SECFailure;
            }
            crv = PK11_GETTAB(context->slot)->C_EncryptUpdate(context->session,
                    random,sizeof(random),out,&length);

            out += length;
            maxout -= length;
            offset = length;
        } else if (context->operation == CKA_DECRYPT) {
            length = sizeof(random);
            crv = PK11_GETTAB(context->slot)->C_DecryptUpdate(context->session,
                    in,sizeof(random),random,&length);
            inlen -= length;
            in += length;
            context->fortezzaHack = PR_FALSE;
        }
    }

    switch (context->operation) {
    case CKA_ENCRYPT:
        length = maxout;
        crv=PK11_GETTAB(context->slot)->C_EncryptUpdate(context->session,
                in, inlen, out, &length);
        length += offset;
        break;
    case CKA_DECRYPT:
        length = maxout;
        crv=PK11_GETTAB(context->slot)->C_DecryptUpdate(context->session,
                in, inlen, out, &length);
        break;
    default:
        crv = CKR_OPERATION_NOT_INITIALIZED;
        break;
    }

    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
        *outlen = 0;
        rv = SECFailure;
    } else {
        *outlen = length;
    }

    if (context->fortezzaHack) {
        if (context->operation == CKA_ENCRYPT) {
            PORT_Assert(allocOut);
            PORT_Memcpy(saveOut, allocOut, length);
            PORT_Free(allocOut);
        }
        context->fortezzaHack = PR_FALSE;
    }

    /*
     * handle session starvation case.. use our last session to multiplex
     */
    if (!context->ownSession) {
        context->savedData = pk11_saveContext(context,context->savedData,
                                              &context->savedLength);
        if (context->savedData == NULL) rv = SECFailure;

        /* clear out out session for others to use */
        pk11_Finalize(context);
    }
    PK11_ExitContextMonitor(context);
    return rv;
}
/*
 * Check the user's password. Log into the card if it's correct.
 * succeed if the user is already logged in.
 */
static SECStatus
pk11_CheckPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
			char *pw, PRBool alreadyLocked, PRBool contextSpecific)
{
    int len = 0;
    CK_RV crv;
    SECStatus rv;
    int64 currtime = PR_Now();
    PRBool mustRetry;
    int retry = 0;

    if (slot->protectedAuthPath) {
	len = 0;
	pw = NULL;
    } else if (pw == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    } else {
	len = PORT_Strlen(pw);
    }

    do {
	if (!alreadyLocked) PK11_EnterSlotMonitor(slot);
	crv = PK11_GETTAB(slot)->C_Login(session,
		contextSpecific ? CKU_CONTEXT_SPECIFIC : CKU_USER,
						(unsigned char *)pw,len);
	slot->lastLoginCheck = 0;
	mustRetry = PR_FALSE;
	if (!alreadyLocked) PK11_ExitSlotMonitor(slot);
	switch (crv) {
	/* if we're already logged in, we're good to go */
	case CKR_OK:
		/* TODO If it was for CKU_CONTEXT_SPECIFIC should we do this */
	    slot->authTransact = PK11_Global.transaction;
	    /* Fall through */
	case CKR_USER_ALREADY_LOGGED_IN:
	    slot->authTime = currtime;
	    rv = SECSuccess;
	    break;
	case CKR_PIN_INCORRECT:
	    PORT_SetError(SEC_ERROR_BAD_PASSWORD);
	    rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
	    break;
	/* someone called reset while we fetched the password, try again once
	 * if the token is still there. */
	case CKR_SESSION_HANDLE_INVALID:
	case CKR_SESSION_CLOSED:
	    if (session != slot->session) {
		/* don't bother retrying, we were in a middle of an operation,
		 * which is now lost. Just fail. */
	        PORT_SetError(PK11_MapError(crv));
	        rv = SECFailure; 
		break;
	    }
	    if (retry++ == 0) {
		rv = PK11_InitToken(slot,PR_FALSE);
		if (rv == SECSuccess) {
		    if (slot->session != CK_INVALID_SESSION) {
			session = slot->session; /* we should have 
						  * a new session now */
			mustRetry = PR_TRUE;
		    } else {
			PORT_SetError(PK11_MapError(crv));
			rv = SECFailure;
		    }
		}
		break;
	    }
	    /* Fall through */
	default:
	    PORT_SetError(PK11_MapError(crv));
	    rv = SECFailure; /* some failure we can't fix by retrying */
	}
    } while (mustRetry);
    return rv;
}
Example #17
0
/*
 * initialize a user PIN Value
 */
SECStatus
PK11_InitPin(PK11SlotInfo *slot, const char *ssopw, const char *userpw)
{
    CK_SESSION_HANDLE rwsession = CK_INVALID_SESSION;
    CK_RV crv;
    SECStatus rv = SECFailure;
    int len;
    int ssolen;

    if (userpw == NULL) userpw = "";
    if (ssopw == NULL) ssopw = "";

    len = PORT_Strlen(userpw);
    ssolen = PORT_Strlen(ssopw);

    /* get a rwsession */
    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
    	PORT_SetError(SEC_ERROR_BAD_DATA);
	slot->lastLoginCheck = 0;
    	return rv;
    }

    if (slot->protectedAuthPath) {
	len = 0;
	ssolen = 0;
	ssopw = NULL;
	userpw = NULL;
    }

    /* check the password */
    crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO, 
					  (unsigned char *)ssopw,ssolen);
    slot->lastLoginCheck = 0;
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError(crv));
	goto done;
    }

    crv = PK11_GETTAB(slot)->C_InitPIN(rwsession,(unsigned char *)userpw,len);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError(crv));
    } else {
    	rv = SECSuccess;
    }

done:
    PK11_GETTAB(slot)->C_Logout(rwsession);
    slot->lastLoginCheck = 0;
    PK11_RestoreROSession(slot,rwsession);
    if (rv == SECSuccess) {
        /* update our view of the world */
        PK11_InitToken(slot,PR_TRUE);
	if (slot->needLogin) {
	    PK11_EnterSlotMonitor(slot);
	    PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
						(unsigned char *)userpw,len);
	    slot->lastLoginCheck = 0;
	    PK11_ExitSlotMonitor(slot);
	}
    }
    return rv;
}
Example #18
0
/*
 * Check the user's password. Log into the card if it's correct.
 * succeed if the user is already logged in.
 */
SECStatus
pk11_CheckPassword(PK11SlotInfo *slot,char *pw)
{
    int len = 0;
    CK_RV crv;
    SECStatus rv;
    int64 currtime = PR_Now();
    PRBool mustRetry;
    int retry = 0;

    if (slot->protectedAuthPath) {
	len = 0;
	pw = NULL;
    } else if (pw == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    } else {
	len = PORT_Strlen(pw);
    }

    do {
	PK11_EnterSlotMonitor(slot);
	crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER,
						(unsigned char *)pw,len);
	slot->lastLoginCheck = 0;
	mustRetry = PR_FALSE;
	PK11_ExitSlotMonitor(slot);
	switch (crv) {
	/* if we're already logged in, we're good to go */
	case CKR_OK:
	    slot->authTransact = PK11_Global.transaction;
	    /* Fall through */
	case CKR_USER_ALREADY_LOGGED_IN:
	    slot->authTime = currtime;
	    rv = SECSuccess;
	    break;
	case CKR_PIN_INCORRECT:
	    PORT_SetError(SEC_ERROR_BAD_PASSWORD);
	    rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
	    break;
	/* someone called reset while we fetched the password, try again once
	 * if the token is still there. */
	case CKR_SESSION_HANDLE_INVALID:
	case CKR_SESSION_CLOSED:
	    if (retry++ == 0) {
		rv = PK11_InitToken(slot,PR_FALSE);
		if (rv == SECSuccess) {
		    if (slot->session != CK_INVALID_SESSION) {
			mustRetry = PR_TRUE;
		    } else {
			PORT_SetError(PK11_MapError(crv));
			rv = SECFailure;
		    }
		}
		break;
	    }
	    /* Fall through */
	default:
	    PORT_SetError(PK11_MapError(crv));
	    rv = SECFailure; /* some failure we can't fix by retrying */
	}
    } while (mustRetry);
    return rv;
}
Example #19
0
SECStatus
PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
				 SECItem *emailProfile,  SECItem *profileTime)
{
    CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
    CK_BBOOL ck_true = CK_TRUE;
    CK_ATTRIBUTE theTemplate[] = {
	{ CKA_CLASS, NULL, 0 },
	{ CKA_TOKEN, NULL, 0 },
	{ CKA_SUBJECT, NULL, 0 },
	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
	{ CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 },
	{ CKA_VALUE, NULL, 0 }
    };
    /* if you change the array, change the variable below as well */
    int realSize = 0;
    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
    CK_ATTRIBUTE *attrs = theTemplate;
    CK_SESSION_HANDLE rwsession;
    PK11SlotInfo *free_slot = NULL;
    CK_RV crv;
#ifdef DEBUG
    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
#endif

    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
    PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true)); attrs++;
    PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); attrs++;
    PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, 
				emailAddr, PORT_Strlen(emailAddr)+1); attrs++;
    if (profileTime) {
	PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data,
	                                            profileTime->len); attrs++;
	PK11_SETATTRS(attrs, CKA_VALUE,emailProfile->data,
	                                            emailProfile->len); attrs++;
    }
    realSize = attrs - theTemplate;
    PORT_Assert (realSize <= tsize);

    if (slot == NULL) {
	free_slot = slot = PK11_GetInternalKeySlot();
	/* we need to free the key slot in the end!!! */
    }

    rwsession = PK11_GetRWSession(slot);
    if (rwsession == CK_INVALID_SESSION) {
	PORT_SetError(SEC_ERROR_READ_ONLY);
	if (free_slot) {
	    PK11_FreeSlot(free_slot);
	}
	return SECFailure;
    }

    crv = PK11_GETTAB(slot)->
                        C_CreateObject(rwsession,theTemplate,realSize,&smimeh);
    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
    }

    PK11_RestoreROSession(slot,rwsession);

    if (free_slot) {
	PK11_FreeSlot(free_slot);
    }
    return SECSuccess;
}
Example #20
0
/*
 * return the certificate associated with a derCert 
 */
SECItem *
PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
				 SECItem *name, SECItem **profileTime)
{
    CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
    CK_ATTRIBUTE theTemplate[] = {
	{ CKA_SUBJECT, NULL, 0 },
	{ CKA_CLASS, NULL, 0 },
	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
    };
    CK_ATTRIBUTE smimeData[] =  {
	{ CKA_SUBJECT, NULL, 0 },
	{ CKA_VALUE, NULL, 0 },
    };
    /* if you change the array, change the variable below as well */
    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
    CK_ATTRIBUTE *attrs = theTemplate;
    CK_RV crv;
    SECItem *emailProfile = NULL;

    if (!emailAddr || !emailAddr[0]) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return NULL;
    }

    PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++;
    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
    PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr)); 
								    attrs++;

    if (*slot) {
    	smimeh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize);
    } else {
	PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
							PR_FALSE,PR_TRUE,NULL);
	PK11SlotListElement *le;

	if (!list) {
	    return NULL;
	}
	/* loop through all the slots */
	for (le = list->head; le; le = le->next) {
	    smimeh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize);
	    if (smimeh != CK_INVALID_HANDLE) {
		*slot = PK11_ReferenceSlot(le->slot);
		break;
	    }
	}
	PK11_FreeSlotList(list);
    }
    
    if (smimeh == CK_INVALID_HANDLE) {
	PORT_SetError(SEC_ERROR_NO_KRL);
	return NULL;
    }

    if (profileTime) {
    	PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0);
    } 
    
    crv = PK11_GetAttributes(NULL,*slot,smimeh,smimeData,2);
    if (crv != CKR_OK) {
	PORT_SetError(PK11_MapError (crv));
	goto loser;
    }

    if (!profileTime) {
	SECItem profileSubject;

	profileSubject.data = (unsigned char*) smimeData[0].pValue;
	profileSubject.len = smimeData[0].ulValueLen;
	if (!SECITEM_ItemsAreEqual(&profileSubject,name)) {
	    goto loser;
	}
    }

    emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
    if (emailProfile == NULL) {
	goto loser;
    }

    emailProfile->data = (unsigned char*) smimeData[1].pValue;
    emailProfile->len = smimeData[1].ulValueLen;

    if (profileTime) {
	*profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
	if (*profileTime) {
	    (*profileTime)->data = (unsigned char*) smimeData[0].pValue;
	    (*profileTime)->len = smimeData[0].ulValueLen;
	}
    }

loser:
    if (emailProfile == NULL) {
	if (smimeData[1].pValue) {
	    PORT_Free(smimeData[1].pValue);
	}
    }
    if (profileTime == NULL || *profileTime == NULL) {
	if (smimeData[0].pValue) {
	    PORT_Free(smimeData[0].pValue);
	}
    }
    return emailProfile;
}
Example #21
0
static SECStatus
pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID,
                          void *arg)
{
    SECItem* derCrl = NULL;
    crlOptions* options = (crlOptions*) arg;
    CERTCrlHeadNode *head = options->head;
    CERTCrlNode *new_node = NULL;
    CK_ATTRIBUTE fetchCrl[3] = {
	 { CKA_VALUE, NULL, 0},
	 { CKA_NETSCAPE_KRL, NULL, 0},
	 { CKA_NETSCAPE_URL, NULL, 0},
    };
    const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
    CK_RV crv;
    SECStatus rv = SECFailure;
    PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory
                                  successfully */
    int i;

    crv = PK11_GetAttributes(NULL,slot,crlID,fetchCrl,fetchCrlSize);
    if (CKR_OK != crv) {
	PORT_SetError(PK11_MapError(crv));
	goto loser;
    }

    if (!fetchCrl[1].pValue) {
        /* reject KRLs */
	PORT_SetError(SEC_ERROR_CRL_INVALID);
	goto loser;
    }

    new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena,
                                              sizeof(CERTCrlNode));
    if (new_node == NULL) {
        goto loser;
    }

    new_node->type = SEC_CRL_TYPE;

    derCrl = SECITEM_AllocItem(NULL, NULL, 0);
    if (!derCrl) {
        goto loser;
    }
    derCrl->type = siBuffer;
    derCrl->data = (unsigned char *)fetchCrl[0].pValue;
    derCrl->len = fetchCrl[0].ulValueLen;
    new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl,new_node->type,
                                               options->decodeOptions);
    if (new_node->crl == NULL) {
	goto loser;
    }    
    adopted = PR_TRUE; /* now that the CRL has adopted the DER memory,
                          we won't need to free it upon exit */

    if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) {
        /* copy the URL if there is one */
        int nnlen = fetchCrl[2].ulValueLen;
        new_node->crl->url  = (char *)PORT_ArenaAlloc(new_node->crl->arena,
                                                      nnlen+1);
        if ( !new_node->crl->url ) {
            goto loser;
        }
        PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
        new_node->crl->url[nnlen] = 0;
    } else {
        new_node->crl->url = NULL;
    }

    new_node->next = NULL;
    if (head->last) {
        head->last->next = new_node;
        head->last = new_node;
    } else {
        head->first = head->last = new_node;
    }
    rv = SECSuccess;
    new_node->crl->slot = PK11_ReferenceSlot(slot);
    new_node->crl->pkcs11ID = crlID;

loser:
    /* free attributes that weren't adopted by the CRL */
    for (i=1;i<fetchCrlSize;i++) {
        if (fetchCrl[i].pValue) {
            PORT_Free(fetchCrl[i].pValue);
        }
    }
    /* free the DER if the CRL object didn't adopt it */
    if (fetchCrl[0].pValue && PR_FALSE == adopted) {
        PORT_Free(fetchCrl[0].pValue);
    }
    if (derCrl && !adopted) {
        /* clear the data fields, which we already took care of above */
        derCrl->data = NULL;
        derCrl->len = 0;
        /* free the memory for the SECItem structure itself */
        SECITEM_FreeItem(derCrl, PR_TRUE);
    }
    return(rv);
}
Example #22
0
static SECStatus
pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg)
{
    SECItem derCrl;
    CERTCrlHeadNode *head = (CERTCrlHeadNode *) arg;
    CERTCrlNode *new_node = NULL;
    CK_ATTRIBUTE fetchCrl[3] = {
	 { CKA_VALUE, NULL, 0},
	 { CKA_NETSCAPE_KRL, NULL, 0},
	 { CKA_NETSCAPE_URL, NULL, 0},
    };
    const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
    CK_RV crv;
    SECStatus rv = SECFailure;

    crv = PK11_GetAttributes(head->arena,slot,crlID,fetchCrl,fetchCrlSize);
    if (CKR_OK != crv) {
	PORT_SetError(PK11_MapError(crv));
	goto loser;
    }

    if (!fetchCrl[1].pValue) {
	PORT_SetError(SEC_ERROR_CRL_INVALID);
	goto loser;
    }

    new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode));
    if (new_node == NULL) {
        goto loser;
    }

    if (*((CK_BBOOL *)fetchCrl[1].pValue))
        new_node->type = SEC_KRL_TYPE;
    else
        new_node->type = SEC_CRL_TYPE;

    derCrl.type = siBuffer;
    derCrl.data = (unsigned char *)fetchCrl[0].pValue;
    derCrl.len = fetchCrl[0].ulValueLen;
    new_node->crl=CERT_DecodeDERCrl(head->arena,&derCrl,new_node->type);
    if (new_node->crl == NULL) {
	goto loser;
    }

    if (fetchCrl[2].pValue) {
        int nnlen = fetchCrl[2].ulValueLen;
        new_node->crl->url  = (char *)PORT_ArenaAlloc(head->arena, nnlen+1);
        if ( !new_node->crl->url ) {
            goto loser;
        }
        PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
        new_node->crl->url[nnlen] = 0;
    } else {
        new_node->crl->url = NULL;
    }


    new_node->next = NULL;
    if (head->last) {
        head->last->next = new_node;
        head->last = new_node;
    } else {
        head->first = head->last = new_node;
    }
    rv = SECSuccess;

loser:
    return(rv);
}
Example #23
0
/*
 * collect the steps we need to initialize a module in a single function
 */
SECStatus
secmod_ModuleInit(SECMODModule *mod, SECMODModule **reload,
                  PRBool *alreadyLoaded)
{
    CK_C_INITIALIZE_ARGS moduleArgs;
    CK_VOID_PTR pInitArgs;
    CK_RV crv;

    if (reload) {
        *reload = NULL;
    }

    if (!mod || !alreadyLoaded) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (mod->libraryParams == NULL) {
        if (mod->isThreadSafe) {
            pInitArgs = (void *)&secmodLockFunctions;
        } else {
            pInitArgs = NULL;
        }
    } else {
        if (mod->isThreadSafe) {
            moduleArgs = secmodLockFunctions;
        } else {
            moduleArgs = secmodNoLockArgs;
        }
        moduleArgs.LibraryParameters = (void *)mod->libraryParams;
        pInitArgs = &moduleArgs;
    }
    crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
    if (CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) {
        SECMODModule *oldModule = NULL;

        /* Library has already been loaded once, if caller expects it, and it
         * has additional configuration, try reloading it as well. */
        if (reload != NULL && mod->libraryParams) {
            oldModule = secmod_FindModuleByFuncPtr(mod->functionList);
        }
        /* Library has been loaded by NSS. It means it may be capable of
         * reloading */
        if (oldModule) {
            SECStatus rv;
            rv = secmod_handleReload(oldModule, mod);
            if (rv == SECSuccess) {
                /* This module should go away soon, since we've
                 * simply expanded the slots on the old module.
                 * When it goes away, it should not Finalize since
                 * that will close our old module as well. Setting
                 * the function list to NULL will prevent that close */
                mod->functionList = NULL;
                *reload = oldModule;
                return SECSuccess;
            }
            SECMOD_DestroyModule(oldModule);
        }
        /* reload not possible, fall back to old semantics */
        if (!enforceAlreadyInitializedError) {
            *alreadyLoaded = PR_TRUE;
            return SECSuccess;
        }
    }
    if (crv != CKR_OK) {
        if (!mod->isThreadSafe ||
            crv == CKR_NETSCAPE_CERTDB_FAILED ||
            crv == CKR_NETSCAPE_KEYDB_FAILED) {
            PORT_SetError(PK11_MapError(crv));
            return SECFailure;
        }
        /* If we had attempted to init a single threaded module "with"
         * parameters and it failed, should we retry "without" parameters?
         * (currently we don't retry in this scenario) */

        if (!loadSingleThreadedModules) {
            PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
            return SECFailure;
        }
        /* If we arrive here, the module failed a ThreadSafe init. */
        mod->isThreadSafe = PR_FALSE;
        if (!mod->libraryParams) {
            pInitArgs = NULL;
        } else {
            moduleArgs = secmodNoLockArgs;
            moduleArgs.LibraryParameters = (void *)mod->libraryParams;
            pInitArgs = &moduleArgs;
        }
        crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
        if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) &&
            (!enforceAlreadyInitializedError)) {
            *alreadyLoaded = PR_TRUE;
            return SECSuccess;
        }
        if (crv != CKR_OK) {
            PORT_SetError(PK11_MapError(crv));
            return SECFailure;
        }
    }
    return SECSuccess;
}
Example #24
0
/*
 * map Stan errors into NSS errors
 * This function examines the stan error stack and automatically sets
 * PORT_SetError(); to the appropriate SEC_ERROR value.
 */
void
CERT_MapStanError()
{
    PRInt32 *errorStack;
    NSSError error, prevError;
    int secError;
    int i;

    error = 0;

    errorStack = NSS_GetErrorStack();
    if (errorStack == 0) {
        PORT_SetError(0);
        return;
    }
    error = prevError = CKR_GENERAL_ERROR;
    /* get the 'top 2' error codes from the stack */
    for (i = 0; errorStack[i]; i++) {
        prevError = error;
        error = errorStack[i];
    }
    if (error == NSS_ERROR_PKCS11) {
        /* map it */
        secError = PK11_MapError(prevError);
    }
    STAN_MAP_ERROR(NSS_ERROR_NO_ERROR, 0)
    STAN_MAP_ERROR(NSS_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_BASE64, SEC_ERROR_BAD_DATA)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_BER, SEC_ERROR_BAD_DER)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ATAV, SEC_ERROR_INVALID_AVA)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_PASSWORD, SEC_ERROR_BAD_PASSWORD)
    STAN_MAP_ERROR(NSS_ERROR_BUSY, SEC_ERROR_BUSY)
    STAN_MAP_ERROR(NSS_ERROR_DEVICE_ERROR, SEC_ERROR_IO)
    STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND,
                   SEC_ERROR_UNKNOWN_ISSUER)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_CERTIFICATE, SEC_ERROR_CERT_NOT_VALID)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_UTF8, SEC_ERROR_BAD_DATA)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_NSSOID, SEC_ERROR_BAD_DATA)

    /* these are library failure for lack of a better error code */
    STAN_MAP_ERROR(NSS_ERROR_NOT_FOUND, SEC_ERROR_LIBRARY_FAILURE)
    STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_IN_CACHE, SEC_ERROR_LIBRARY_FAILURE)
    STAN_MAP_ERROR(NSS_ERROR_MAXIMUM_FOUND, SEC_ERROR_LIBRARY_FAILURE)
    STAN_MAP_ERROR(NSS_ERROR_USER_CANCELED, SEC_ERROR_LIBRARY_FAILURE)
    STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE)
    STAN_MAP_ERROR(NSS_ERROR_ALREADY_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE)
    STAN_MAP_ERROR(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD,
                   SEC_ERROR_LIBRARY_FAILURE)
    STAN_MAP_ERROR(NSS_ERROR_HASH_COLLISION, SEC_ERROR_LIBRARY_FAILURE)

    STAN_MAP_ERROR(NSS_ERROR_INTERNAL_ERROR, SEC_ERROR_LIBRARY_FAILURE)

    /* these are all invalid arguments */
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARGUMENT, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_POINTER, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA_MARK, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_DUPLICATE_POINTER, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_POINTER_NOT_REGISTERED, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_EMPTY, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_VALUE_TOO_LARGE, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_UNSUPPORTED_TYPE, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_BUFFER_TOO_SHORT, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ATOB_CONTEXT, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_BTOA_CONTEXT, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ITEM, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_STRING, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1ENCODER, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1DECODER, SEC_ERROR_INVALID_ARGS)
    STAN_MAP_ERROR(NSS_ERROR_UNKNOWN_ATTRIBUTE, SEC_ERROR_INVALID_ARGS)
    else { secError = SEC_ERROR_LIBRARY_FAILURE; }
    PORT_SetError(secError);
}
Example #25
0
/*
 * Digest a key if possible./
 */
SECStatus
PK11_DigestKey(PK11Context *context, PK11SymKey *key)
{
    CK_RV crv = CKR_OK;
    SECStatus rv = SECSuccess;
    PK11SymKey *newKey = NULL;

    if (!context || !key) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /* if we ran out of session, we need to restore our previously stored
     * state.
     */
    if (context->slot != key->slot) {
        newKey = pk11_CopyToSlot(context->slot,CKM_SSL3_SHA1_MAC,CKA_SIGN,key);
    } else {
        newKey = PK11_ReferenceSymKey(key);
    }

    context->init = PR_FALSE;
    PK11_EnterContextMonitor(context);
    if (!context->ownSession) {
        rv = pk11_restoreContext(context,context->savedData,
                                 context->savedLength);
        if (rv != SECSuccess) {
            PK11_ExitContextMonitor(context);
            PK11_FreeSymKey(newKey);
            return rv;
        }
    }


    if (newKey == NULL) {
        crv = CKR_KEY_TYPE_INCONSISTENT;
        if (key->data.data) {
            crv=PK11_GETTAB(context->slot)->C_DigestUpdate(context->session,
                    key->data.data,key->data.len);
        }
    } else {
        crv=PK11_GETTAB(context->slot)->C_DigestKey(context->session,
                newKey->objectID);
    }

    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
        rv = SECFailure;
    }

    /*
     * handle session starvation case.. use our last session to multiplex
     */
    if (!context->ownSession) {
        context->savedData = pk11_saveContext(context,context->savedData,
                                              &context->savedLength);
        if (context->savedData == NULL) rv = SECFailure;

        /* clear out out session for others to use */
        pk11_Finalize(context);
    }
    PK11_ExitContextMonitor(context);
    if (newKey) PK11_FreeSymKey(newKey);
    return rv;
}
Example #26
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;
}
Example #27
0
/*
 * clean up a cipher operation, so the session can be used by
 * someone new.
 */
SECStatus
pk11_Finalize(PK11Context *context)
{
    CK_ULONG count = 0;
    CK_RV crv;
    unsigned char stackBuf[256];
    unsigned char *buffer = NULL;

    if (!context->ownSession) {
        return SECSuccess;
    }

finalize:
    switch (context->operation) {
    case CKA_ENCRYPT:
        crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
                buffer, &count);
        break;
    case CKA_DECRYPT:
        crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
                buffer, &count);
        break;
    case CKA_SIGN:
        crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
                buffer, &count);
        break;
    case CKA_VERIFY:
        crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
                buffer, count);
        break;
    case CKA_DIGEST:
        crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
                buffer, &count);
        break;
    default:
        crv = CKR_OPERATION_NOT_INITIALIZED;
        break;
    }

    if (crv != CKR_OK) {
        if (buffer != stackBuf) {
            PORT_Free(buffer);
        }
        if (crv == CKR_OPERATION_NOT_INITIALIZED) {
            /* if there's no operation, it is finalized */
            return SECSuccess;
        }
        PORT_SetError( PK11_MapError(crv) );
        return SECFailure;
    }

    /* try to finalize the session with a buffer */
    if (buffer == NULL) {
        if (count <= sizeof stackBuf) {
            buffer = stackBuf;
        } else {
            buffer = PORT_Alloc(count);
            if (buffer == NULL) {
                PORT_SetError(SEC_ERROR_NO_MEMORY);
                return SECFailure;
            }
        }
        goto finalize;
    }
    if (buffer != stackBuf) {
        PORT_Free(buffer);
    }
    return SECSuccess;
}
Example #28
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;
}