Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -551,16 +551,17 @@ CACKEY_TLV_OBJID_CAC_PERSONNEL = 0x0201, CACKEY_TLV_OBJID_CAC_PKICERT = 0x02FE } cackey_tlv_objectid; typedef enum { - CACKEY_PCSC_S_TOKENPRESENT = 2, - CACKEY_PCSC_S_TOKENABSENT = 1, + CACKEY_PCSC_S_TOKENPRESENT = 1, CACKEY_PCSC_S_OK = 0, CACKEY_PCSC_E_GENERIC = -1, CACKEY_PCSC_E_BADPIN = -2, CACKEY_PCSC_E_LOCKED = -3, + CACKEY_PCSC_E_NEEDLOGIN = -4, + CACKEY_PCSC_E_TOKENABSENT = -6, } cackey_ret; struct cackey_tlv_cardurl { unsigned char rid[5]; cackey_tlv_apptype apptype; @@ -1067,10 +1068,15 @@ CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len); } recv_len = sizeof(recv_buf); scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len); + if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) { + CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = SCARD_E_NOT_TRANSACTED), retrying..."); + + scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len); + } if (scard_xmit_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret); CACKEY_DEBUG_PRINTF("Marking slot as having been reset"); slot->transaction_depth = 0; @@ -1098,11 +1104,11 @@ /* End Smartcard Transaction */ slot->transaction_depth = 1; cackey_end_transaction(slot); - return(CACKEY_PCSC_E_GENERIC); + return(CACKEY_PCSC_E_TOKENABSENT); } } else { CACKEY_DEBUG_PRINTF("Disconnecting card"); SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD); @@ -1111,11 +1117,11 @@ /* End Smartcard Transaction */ slot->transaction_depth = 1; cackey_end_transaction(slot); CACKEY_DEBUG_PRINTF("Returning in failure"); - return(CACKEY_PCSC_E_GENERIC); + return(CACKEY_PCSC_E_TOKENABSENT); } } else { CACKEY_DEBUG_PRINTF("Disconnecting card"); SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD); @@ -1124,11 +1130,11 @@ /* End Smartcard Transaction */ slot->transaction_depth = 1; cackey_end_transaction(slot); CACKEY_DEBUG_PRINTF("Returning in failure"); - return(CACKEY_PCSC_E_GENERIC); + return(CACKEY_PCSC_E_TOKENABSENT); } } CACKEY_DEBUG_PRINTBUF("Returned Value:", recv_buf, recv_len); @@ -1974,22 +1980,36 @@ send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen); if (send_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error."); - if (respcode == 0x6982) { - CACKEY_DEBUG_PRINTF("Security status not satisified."); - } - if (free_tmpbuf) { if (tmpbuf_s) { free(tmpbuf_s); } } /* End transaction */ cackey_end_transaction(slot); + + if (respcode == 0x6982) { + CACKEY_DEBUG_PRINTF("Security status not satisified. Returning NEEDLOGIN"); + + slot->slot_reset = 1; + slot->token_flags = CKF_LOGIN_REQUIRED; + + return(CACKEY_PCSC_E_NEEDLOGIN); + } + + if (send_ret == CACKEY_PCSC_E_TOKENABSENT) { + CACKEY_DEBUG_PRINTF("Token absent. Returning TOKENABSENT"); + + slot->slot_reset = 1; + slot->token_flags = CKF_LOGIN_REQUIRED; + + return(CACKEY_PCSC_E_TOKENABSENT); + } return(-1); } tmpbuf += bytes_to_send; @@ -2186,11 +2206,11 @@ pcsc_connect_ret = cackey_connect_card(slot); if (pcsc_connect_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent"); - return(CACKEY_PCSC_S_TOKENABSENT); + return(CACKEY_PCSC_E_TOKENABSENT); } atr_len = sizeof(atr); status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len); if (status_ret != SCARD_S_SUCCESS) { @@ -2211,28 +2231,28 @@ CACKEY_DEBUG_PRINTF("Reset successful, requerying"); status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len); if (status_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret)); - return(CACKEY_PCSC_S_TOKENABSENT); + return(CACKEY_PCSC_E_TOKENABSENT); } } else { CACKEY_DEBUG_PRINTF("Unable to reconnect to card, returning token absent. SCardReconnect() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_reconn_ret)); - return(CACKEY_PCSC_S_TOKENABSENT); + return(CACKEY_PCSC_E_TOKENABSENT); } } else { CACKEY_DEBUG_PRINTF("Unable to query card status, returning token absent. SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret)); - return(CACKEY_PCSC_S_TOKENABSENT); + return(CACKEY_PCSC_E_TOKENABSENT); } } if ((state & SCARD_ABSENT) == SCARD_ABSENT) { CACKEY_DEBUG_PRINTF("Card is absent, returning token absent"); - return(CACKEY_PCSC_S_TOKENABSENT); + return(CACKEY_PCSC_E_TOKENABSENT); } CACKEY_DEBUG_PRINTF("Returning token present."); return(CACKEY_PCSC_S_TOKENPRESENT); @@ -4806,11 +4826,17 @@ /* Ask card to decrypt */ 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; + if (buflen == CACKEY_PCSC_E_NEEDLOGIN) { + retval = CKR_USER_NOT_LOGGED_IN; + } else if (buflen == CACKEY_PCSC_E_TOKENABSENT) { + retval = CKR_DEVICE_REMOVED; + } else { + retval = CKR_GENERAL_ERROR; + } } else if (((unsigned long) buflen) > *pulPartLen && pPart) { /* Decrypted data too large */ retval = CKR_BUFFER_TOO_SMALL; } else { if (pPart) { @@ -5276,11 +5302,17 @@ 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[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; + if (sigbuflen == CACKEY_PCSC_E_NEEDLOGIN) { + retval = CKR_USER_NOT_LOGGED_IN; + } else if (sigbuflen == CACKEY_PCSC_E_TOKENABSENT) { + retval = CKR_DEVICE_REMOVED; + } else { + retval = CKR_GENERAL_ERROR; + } } else if (((unsigned long) sigbuflen) > *pulSignatureLen && pSignature) { /* Signed data too large */ CACKEY_DEBUG_PRINTF("retval = CKR_BUFFER_TOO_SMALL; sigbuflen = %lu, pulSignatureLen = %lu", (unsigned long) sigbuflen, (unsigned long) *pulSignatureLen); retval = CKR_BUFFER_TOO_SMALL;