@@ -3859,10 +3859,11 @@ return(CKR_FUNCTION_NOT_SUPPORTED); } CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { + CK_SLOT_ID slotID; int mutex_retval; int tries_remaining; int login_ret; CACKEY_DEBUG_PRINTF("Called."); @@ -3898,27 +3899,43 @@ CACKEY_DEBUG_PRINTF("Error. Session not active."); return(CKR_SESSION_HANDLE_INVALID); } - login_ret = cackey_login(&cackey_slots[cackey_sessions[hSession].slotID], pPin, ulPinLen, &tries_remaining); + slotID = cackey_sessions[hSession].slotID; + + if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID); + + return(CKR_GENERAL_ERROR); + } + + if (cackey_slots[slotID].active == 0) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID); + + cackey_mutex_unlock(cackey_biglock); + + return(CKR_GENERAL_ERROR); + } + + login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining); if (login_ret != CACKEY_PCSC_S_OK) { cackey_mutex_unlock(cackey_biglock); if (login_ret == CACKEY_PCSC_E_LOCKED) { CACKEY_DEBUG_PRINTF("Error. Token is locked."); - cackey_slots[cackey_sessions[hSession].slotID].token_flags |= CKF_USER_PIN_LOCKED; + cackey_slots[slotID].token_flags |= CKF_USER_PIN_LOCKED; return(CKR_PIN_LOCKED); } else if (login_ret == CACKEY_PCSC_E_BADPIN) { CACKEY_DEBUG_PRINTF("Error. Invalid PIN."); - cackey_slots[cackey_sessions[hSession].slotID].token_flags |= CKF_USER_PIN_COUNT_LOW; + cackey_slots[slotID].token_flags |= CKF_USER_PIN_COUNT_LOW; if (tries_remaining == 1) { - cackey_slots[cackey_sessions[hSession].slotID].token_flags |= CKF_USER_PIN_FINAL_TRY; + cackey_slots[slotID].token_flags |= CKF_USER_PIN_FINAL_TRY; } return(CKR_PIN_INCORRECT); } @@ -3925,11 +3942,11 @@ CACKEY_DEBUG_PRINTF("Error. Unknown error returned from cackey_login() (%i)", login_ret); return(CKR_GENERAL_ERROR); } - cackey_slots[cackey_sessions[hSession].slotID].token_flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_COUNT_LOW | CKF_LOGIN_REQUIRED | CKF_USER_PIN_FINAL_TRY); + cackey_slots[slotID].token_flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_COUNT_LOW | CKF_LOGIN_REQUIRED | CKF_USER_PIN_FINAL_TRY); cackey_sessions[hSession].state = CKS_RO_USER_FUNCTIONS; mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) { @@ -3942,10 +3959,11 @@ return(CKR_OK); } CK_DEFINE_FUNCTION(CK_RV, C_Logout)(CK_SESSION_HANDLE hSession) { + CK_SLOT_ID slotID; int mutex_retval; CACKEY_DEBUG_PRINTF("Called."); if (!cackey_initialized) { @@ -3972,12 +3990,29 @@ CACKEY_DEBUG_PRINTF("Error. Session not active."); return(CKR_SESSION_HANDLE_INVALID); } + + slotID = cackey_sessions[hSession].slotID; + + if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID); + + return(CKR_GENERAL_ERROR); + } + + if (cackey_slots[slotID].active == 0) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID); + + cackey_mutex_unlock(cackey_biglock); + + return(CKR_GENERAL_ERROR); + } cackey_sessions[hSession].state = CKS_RO_PUBLIC_SESSION; + cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED; mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) { CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); @@ -4179,10 +4214,11 @@ return(CKR_FUNCTION_NOT_SUPPORTED); } CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { + CK_SLOT_ID slotID; int mutex_retval; CACKEY_DEBUG_PRINTF("Called."); if (!cackey_initialized) { @@ -4218,31 +4254,47 @@ CACKEY_DEBUG_PRINTF("Error. Search already active."); return(CKR_OPERATION_ACTIVE); } - if (cackey_slots[cackey_sessions[hSession].slotID].slot_reset) { + slotID = cackey_sessions[hSession].slotID; + + if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID); + + return(CKR_GENERAL_ERROR); + } + + if (cackey_slots[slotID].active == 0) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID); + + cackey_mutex_unlock(cackey_biglock); + + return(CKR_GENERAL_ERROR); + } + + if (cackey_slots[slotID].slot_reset) { CACKEY_DEBUG_PRINTF("The slot has been reset since we last looked for identities -- rescanning"); if (cackey_sessions[hSession].identities != NULL) { cackey_free_identities(cackey_sessions[hSession].identities, cackey_sessions[hSession].identities_count); cackey_sessions[hSession].identities = NULL; cackey_sessions[hSession].identities_count = 0; } - if (cackey_slots[cackey_sessions[hSession].slotID].label != NULL) { - free(cackey_slots[cackey_sessions[hSession].slotID].label); - cackey_slots[cackey_sessions[hSession].slotID].label = NULL; + if (cackey_slots[slotID].label != NULL) { + free(cackey_slots[slotID].label); + cackey_slots[slotID].label = NULL; } - cackey_slots[cackey_sessions[hSession].slotID].slot_reset = 0; - cackey_slots[cackey_sessions[hSession].slotID].token_flags = CKF_LOGIN_REQUIRED; + cackey_slots[slotID].slot_reset = 0; + cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED; } if (cackey_sessions[hSession].identities == NULL) { - cackey_sessions[hSession].identities = cackey_read_identities(&cackey_slots[cackey_sessions[hSession].slotID], &cackey_sessions[hSession].identities_count); + cackey_sessions[hSession].identities = cackey_read_identities(&cackey_slots[slotID], &cackey_sessions[hSession].identities_count); } if (pTemplate != NULL) { if (ulCount != 0) { cackey_sessions[hSession].search_query_count = ulCount; @@ -4665,10 +4717,11 @@ } CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { static CK_BYTE buf[16384]; ssize_t buflen; + CK_SLOT_ID slotID; CK_RV retval = CKR_GENERAL_ERROR; int mutex_retval; CACKEY_DEBUG_PRINTF("Called."); @@ -4729,15 +4782,31 @@ CACKEY_DEBUG_PRINTF("Error. Decrypt not active."); return(CKR_OPERATION_NOT_INITIALIZED); } + + slotID = cackey_sessions[hSession].slotID; + + if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID); + + return(CKR_GENERAL_ERROR); + } + + if (cackey_slots[slotID].active == 0) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID); + + cackey_mutex_unlock(cackey_biglock); + + return(CKR_GENERAL_ERROR); + } switch (cackey_sessions[hSession].decrypt_mechanism) { case CKM_RSA_PKCS: /* Ask card to decrypt */ - buflen = cackey_signdecrypt(&cackey_slots[cackey_sessions[hSession].slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1); + buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1); if (buflen < 0) { /* Decryption failed. */ retval = CKR_GENERAL_ERROR; } else if (((unsigned long) buflen) > *pulPartLen && pPart) { @@ -5135,10 +5204,11 @@ } CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { static CK_BYTE sigbuf[1024]; ssize_t sigbuflen; + CK_SLOT_ID slotID; CK_RV retval = CKR_GENERAL_ERROR; int terminate_sign = 1; int mutex_retval; CACKEY_DEBUG_PRINTF("Called."); @@ -5181,16 +5251,32 @@ CACKEY_DEBUG_PRINTF("Error. Sign not active."); return(CKR_OPERATION_NOT_INITIALIZED); } + + slotID = cackey_sessions[hSession].slotID; + + if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID); + + return(CKR_GENERAL_ERROR); + } + + if (cackey_slots[slotID].active == 0) { + CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID); + + cackey_mutex_unlock(cackey_biglock); + + return(CKR_GENERAL_ERROR); + } switch (cackey_sessions[hSession].sign_mechanism) { case CKM_RSA_PKCS: /* Ask card to sign */ CACKEY_DEBUG_PRINTF("Asking to sign from identity %p in session %lu", cackey_sessions[hSession].sign_identity, (unsigned long) hSession); - sigbuflen = cackey_signdecrypt(&cackey_slots[cackey_sessions[hSession].slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0); + sigbuflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0); if (sigbuflen < 0) { /* Signing failed. */ retval = CKR_GENERAL_ERROR; } else if (((unsigned long) sigbuflen) > *pulSignatureLen && pSignature) {