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 + -
显示快捷键?