pk11slot.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,388 行 · 第 1/5 页

C
2,388
字号
    CK_RV crv;    PRBool alloced = PR_FALSE;    PK11SlotInfo *intern = PK11_GetInternalSlot();    /* if we couldn't initialize an internal module,      * we can't check external ones */    if (intern == NULL) return PR_FALSE;    /* first get the count of mechanisms */    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,NULL,&count);    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    if (crv != CKR_OK) {	PK11_FreeSlot(intern);	return PR_FALSE;    }    /* don't blow up just because the card supports more mechanisms than     * we know about, just alloc space for them */    if (count > MAX_MECH_LIST_SIZE) {    	mechList = (CK_MECHANISM_TYPE *)			    PORT_Alloc(count *sizeof(CK_MECHANISM_TYPE));	alloced = PR_TRUE;	if (mechList == NULL) return PR_FALSE;    }    /* get the list */    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    crv =PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID, mechList, &count);    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    if (crv != CKR_OK) {	if (alloced) PORT_Free(mechList);	PK11_FreeSlot(intern);	return PR_FALSE;    }    if (!generated) {	data.data = dataV;	data.len = sizeof(dataV);	iv.data = ivV;	iv.len = sizeof(ivV);	/* ok, this is a cheat, we know our internal random number generater	 * is thread safe */	PK11_GETTAB(intern)->C_GenerateRandom(intern->session,							data.data, data.len);	PK11_GETTAB(intern)->C_GenerateRandom(intern->session,							iv.data, iv.len);    }    for (i=0; i < (int) count; i++) {	switch (mechList[i]) {	case CKM_DES_CBC:	case CKM_DES_ECB:	case CKM_RC4:	case CKM_RC2_CBC:	case CKM_RC2_ECB:	    if (!PK11_VerifyMechanism(slot,intern,mechList[i],&data,&iv)){		if (alloced) PORT_Free(mechList);    		PK11_FreeSlot(intern);		return PR_FALSE;	    }	}    }    if (alloced) PORT_Free(mechList);    PK11_FreeSlot(intern);    return PR_TRUE;}/* * See if we need to run the verify test, do so if necessary. If we fail, * disable the slot. */    SECStatuspk11_CheckVerifyTest(PK11SlotInfo *slot){    PK11_EnterSlotMonitor(slot);    if (slot->needTest) {	slot->needTest = PR_FALSE;     	PK11_ExitSlotMonitor(slot);	if (!PK11_VerifySlotMechanisms(slot)) {	    (void)PK11_GETTAB(slot)->C_CloseSession(slot->session);	    slot->session = CK_INVALID_SESSION;	    PK11_ClearSlotList(slot);	    slot->disabled = PR_TRUE;	    slot->reason = PK11_DIS_TOKEN_VERIFY_FAILED;	    slot->needTest = PR_TRUE;	    PORT_SetError(SEC_ERROR_IO);	    return SECFailure;	}    } else {    	PK11_ExitSlotMonitor(slot);    }    return SECSuccess;}/* * Reads in the slots mechanism list for later use */SECStatusPK11_ReadMechanismList(PK11SlotInfo *slot){    CK_ULONG count;    CK_RV crv;    if (slot->mechanismList) {	PORT_Free(slot->mechanismList);	slot->mechanismList = NULL;    }    slot->mechanismCount = 0;    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,NULL,&count);    if (crv != CKR_OK) {	if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);	PORT_SetError(PK11_MapError(crv));	return SECFailure;    }    slot->mechanismList = (CK_MECHANISM_TYPE *)			    PORT_Alloc(count *sizeof(CK_MECHANISM_TYPE));    if (slot->mechanismList == NULL) {	if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);	return SECFailure;    }    crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,						slot->mechanismList, &count);    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    if (crv != CKR_OK) {	PORT_Free(slot->mechanismList);	slot->mechanismList = NULL;	PORT_SetError(PK11_MapError(crv));	return SECSuccess;    }    slot->mechanismCount = count;    return SECSuccess;}/* * initialize a new token * unlike initialize slot, this can be called multiple times in the lifetime * of NSS. It reads the information associated with a card or token, * that is not going to change unless the card or token changes. */SECStatusPK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts){    CK_TOKEN_INFO tokenInfo;    CK_RV crv;    char *tmp;    SECStatus rv;    /* set the slot flags to the current token values */    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,&tokenInfo);    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    if (crv != CKR_OK) {	PORT_SetError(PK11_MapError(crv));	return SECFailure;    }    /* set the slot flags to the current token values */    slot->series++; /* allow other objects to detect that the 		      * slot is different */    slot->flags = tokenInfo.flags;    slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ? 							PR_TRUE : PR_FALSE);    slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ? 							PR_TRUE : PR_FALSE);    slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);    tmp = PK11_MakeString(NULL,slot->token_name,			(char *)tokenInfo.label, sizeof(tokenInfo.label));    slot->minPassword = tokenInfo.ulMinPinLen;    slot->maxPassword = tokenInfo.ulMaxPinLen;    PORT_Memcpy(slot->serial,tokenInfo.serialNumber,sizeof(slot->serial));    slot->defRWSession = (PRBool)((!slot->readOnly) && 					(tokenInfo.ulMaxSessionCount == 1));    rv = PK11_ReadMechanismList(slot);    if (rv != SECSuccess) return rv;    slot->hasRSAInfo = PR_FALSE;    slot->RSAInfoFlags = 0;    /* initialize the maxKeyCount value */    if (tokenInfo.ulMaxSessionCount == 0) {	slot->maxKeyCount = 300; /* should be #define or a config param */    } else if (tokenInfo.ulMaxSessionCount < 20) {	/* don't have enough sessions to keep that many keys around */	slot->maxKeyCount = 0;    } else {	slot->maxKeyCount = tokenInfo.ulMaxSessionCount/2;    }    /* Make sure our session handle is valid */    if (slot->session == CK_INVALID_SESSION) {	/* we know we don't have a valid session, go get one */	CK_SESSION_HANDLE session;	/* session should be Readonly, serial */	if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);	crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,	      (slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,				  slot,pk11_notify,&session);	if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);	if (crv != CKR_OK) {	    PORT_SetError(PK11_MapError(crv));	    return SECFailure;	}	slot->session = session;    } else {	/* The session we have may be defunct (the token associated with it)	 * has been removed   */	CK_SESSION_INFO sessionInfo;	if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);	crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session,&sessionInfo);        if (crv == CKR_DEVICE_ERROR) {	    PK11_GETTAB(slot)->C_CloseSession(slot->session);	    crv = CKR_SESSION_CLOSED;	}	if ((crv==CKR_SESSION_CLOSED) || (crv==CKR_SESSION_HANDLE_INVALID)) {	    crv =PK11_GETTAB(slot)->C_OpenSession(slot->slotID,	      (slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,					slot,pk11_notify,&slot->session);	    if (crv != CKR_OK) {	        PORT_SetError(PK11_MapError(crv));		slot->session = CK_INVALID_SESSION;		if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);		return SECFailure;	    }	}	if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    }    /*if we have cached slotcerts, free them they are almost certainly stale*/    PK11_FreeSlotCerts(slot);    if (loadCerts && (!slot->isInternal) &&        ((!slot->needLogin) || (slot->defaultFlags & SECMOD_FRIENDLY_FLAG))) {	PK11_ReadSlotCerts(slot);    }    if (!(slot->needLogin)) {	return pk11_CheckVerifyTest(slot);    }    if (!(slot->isInternal) && (slot->hasRandom)) {	/* if this slot has a random number generater, use it to add entropy	 * to the internal slot. */	PK11SlotInfo *int_slot = PK11_GetInternalSlot();	if (int_slot) {	    unsigned char random_bytes[32];	    /* if this slot can issue random numbers, get some entropy from	     * that random number generater and give it to our internal token.	     */	    PK11_EnterSlotMonitor(slot);	    crv = PK11_GETTAB(slot)->C_GenerateRandom			(slot->session,random_bytes, sizeof(random_bytes));	    PK11_ExitSlotMonitor(slot);	    if (crv == CKR_OK) {	        PK11_EnterSlotMonitor(int_slot);		PK11_GETTAB(int_slot)->C_SeedRandom(int_slot->session,					random_bytes, sizeof(random_bytes));	        PK11_ExitSlotMonitor(int_slot);	    }	    /* Now return the favor and send entropy to the token's random 	     * number generater */	    PK11_EnterSlotMonitor(int_slot);	    crv = PK11_GETTAB(int_slot)->C_GenerateRandom(int_slot->session,					random_bytes, sizeof(random_bytes));	    PK11_ExitSlotMonitor(int_slot);	    if (crv == CKR_OK) {	        PK11_EnterSlotMonitor(slot);		PK11_GETTAB(slot)->C_SeedRandom(slot->session,					random_bytes, sizeof(random_bytes));	        PK11_ExitSlotMonitor(slot);	    }	}    }	    return SECSuccess;}static PRBoolpk11_isRootSlot(PK11SlotInfo *slot) {    CK_ATTRIBUTE findTemp[1];    CK_ATTRIBUTE *attrs;    CK_OBJECT_CLASS oclass = CKO_NETSCAPE_BUILTIN_ROOT_LIST;    int tsize;    CK_OBJECT_HANDLE handle;    attrs = findTemp;    PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass)); attrs++;    tsize = attrs - findTemp;    PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));    handle = pk11_FindObjectByTemplate(slot,findTemp,tsize);    if (handle == CK_INVALID_KEY) {	return PR_FALSE;    }    return PR_TRUE;}/* * Initialize the slot : * This initialization code is called on each slot a module supports when * it is loaded. It does the bringup initialization. The difference between * this and InitToken is Init slot does those one time initialization stuff, * usually associated with the reader, while InitToken may get called multiple * times as tokens are removed and re-inserted. */voidPK11_InitSlot(SECMODModule *mod,CK_SLOT_ID slotID,PK11SlotInfo *slot){    SECStatus rv;    char *tmp;    CK_SLOT_INFO slotInfo;    slot->functionList = mod->functionList;    slot->isInternal = mod->internal;    slot->slotID = slotID;    slot->isThreadSafe = mod->isThreadSafe;    slot->hasRSAInfo = PR_FALSE;        if (PK11_GETTAB(slot)->C_GetSlotInfo(slotID,&slotInfo) != CKR_OK) {	slot->disabled = PR_TRUE;	slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;	return;    }    /* test to make sure claimed mechanism work */    slot->needTest = mod->internal ? PR_FALSE : PR_TRUE;    slot->module = mod; /* NOTE: we don't make a reference here because			 * modules have references to their slots. This			 * works because modules keep implicit references			 * from their slots, and won't unload and disappear			 * until all their slots have been freed */    tmp = PK11_MakeString(NULL,slot->slot_name,	 (char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription));    slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT);    if ((slotInfo.flags & CKF_REMOVABLE_DEVICE) == 0) {	slot->isPerm = PR_TRUE;	/* permanment slots must have the token present always */	if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {	    slot->disabled = PR_TRUE;	    slot->reason = PK11_DIS_TOKEN_NOT_PRESENT;	    return; /* nothing else to do */	}    }    /* if the token is present, initialize it */    if ((slotInfo.flags & CKF_TOKEN_PRESENT) != 0) {	rv = PK11_InitToken(slot,PR_TRUE);	/* the only hard failures are on permanent devices, or function	 * verify failures... function verify failures are already handled	 * by tokenInit */	if ((rv != SECSuccess) && (slot->isPerm) && (!slot->disabled)) {	    slot->disabled = PR_TRUE;	    slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;	}    }    if (pk11_isRootSlot(slot)) {	slot->hasRootCerts= PR_TRUE;    }}	/********************************************************************* *            Slot mapping utility functions. *********************************************************************//* * determine if the token is present. If the token is present, make sure * we have a valid session handle. Also set the value of needLogin  * appropriately. */static PRBoolpk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts){    CK_SLOT_INFO slotInfo;    CK_SESSION_INFO sessionInfo;    CK_RV crv;    /* disabled slots are never present */    if (slot->disabled) {	return PR_FALSE;    }    /* permanent slots are always present */    if (slot->isPerm && (slot->session != CK_INVALID_SESSION)) {	return PR_TRUE;    }    /* removable slots have a flag that says they are present */    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    if (PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID,&slotInfo) != CKR_OK) {        if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);	return PR_FALSE;    }    if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {	/* if the slot is no longer present, close the session */	if (slot->session != CK_INVALID_SESSION) {	    PK11_GETTAB(slot)->C_CloseSession(slot->session);	    slot->session = CK_INVALID_SESSION;	    /* force certs to be freed */	    PK11_FreeSlotCerts(slot);	}        if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);	return PR_FALSE;    }    /* use the session Info to determine if the card has been removed and then     * re-inserted */    if (slot->session != CK_INVALID_SESSION) {	crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo);	if (crv != CKR_OK) {	    PK11_GETTAB(slot)->C_CloseSession(slot->session);	    slot->session = CK_INVALID_SESSION;	    PK11_FreeSlotCerts(slot);	}    }    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    /* card has not been removed, current token info is correct */    if (slot->session != CK_INVALID_SESSION) return PR_TRUE;    /* initialize the token info state */    if (PK11_InitToken(slot,loadCerts) != SECSuccess) {	return PR_FALSE;    }    return PR_TRUE;}/* * old version of the routine */PRBoolPK11_IsPresent(PK11SlotInfo *slot) {   return pk11_IsPresentCertLoad(slot,PR_TRUE);}/* is the slot disabled? */PRBoolPK11_IsDisabled(PK11SlotInfo *slot){    return slot->disabled;}/* and why? */PK11DisableReasonsPK11_GetDisabledReason(PK11SlotInfo *slot){    return slot->reason;}/* returns PR_TRUE if successfully disable the slot *//* returns PR_FALSE otherwise */PRBool PK11_UserDisableSlot(PK11SlotInfo *slot) {    slot->defaultFlags |= PK11_DISABLE_FLAG;    slot->disabled = PR_TRUE;    slot->reason = PK11_DIS_USER_SELECTED;        return PR_TRUE;}PRBool PK11_UserEnableSlot(PK11SlotInfo *slot) {    slot->defaultFlags &= ~PK11_DISABLE_FLAG;    slot->disabled = PR_FALSE;    slot->reason = PK11_DIS_NONE;    return PR_TRUE;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?