Index: build/cackey_osx_build/Template_pmbuild/index.xml.in ================================================================== --- build/cackey_osx_build/Template_pmbuild/index.xml.in +++ build/cackey_osx_build/Template_pmbuild/index.xml.in @@ -32,11 +32,11 @@ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \f0\fs26 \cf0 Release information:\ pkg: CACKey\ author: US Army Corps of Engineers\ -Mac build contact: Kenneth Van Alstyne \ +Mac build contact: Kenneth Van Alstyne \ US Department of Homeland Security\ contact: Roy Keene \ ------------------------------------------------\ \ The PKCS11.tokend connector module included in this package is licensed under\ @@ -77,13 +77,10 @@ A debug version, /Library/CACKey/libcackey_g.dylib is provided if debug output is necessary.}]]> - - This CACKey release requires Mac OS X @@CUROSXVER@@. - This CACKey release requires Mac OS X @@CUROSXVER@@. Index: build/cackey_osx_build/build_osx.sh ================================================================== --- build/cackey_osx_build/build_osx.sh +++ build/cackey_osx_build/build_osx.sh @@ -14,11 +14,11 @@ echo "Usage: build_osx.sh " echo Where target is one of: echo " leopard - (Builds Universal 10.5 Library for PPCG4/i386)" echo " snowleopard - (Builds Universal 10.6 Library for i386/x86_64)" echo " lion - (Builds Universal 10.7 Library for i386/x86_64)" - echo " sltoml - (Builds Universal 10.6/10.7/10.8 Library for i386/x86_64)" + echo " sltomav - (Builds Universal 10.6/10.7/10.8/10.9 Library for i386/x86_64)" echo " all - (Builds for all supported targets)" echo " clean - (Cleans up)" echo "Run from CACKey Build Root." exit $? } @@ -43,11 +43,11 @@ if [ ! -d macbuild ]; then mkdir macbuild mkdir macbuild/Leopard mkdir macbuild/Snowleopard mkdir macbuild/Lion - mkdir macbuild/Sltoml + mkdir macbuild/Sltomav mkdir macbuild/pkg fi if [ ! -f config.guess ]; then cp ${LIBTOOLDIR}/config.guess . fi @@ -68,11 +68,10 @@ ARCHLIST="" DLIB="" DARCHLIST="" OSX=Leopard PKTARGETOS=3 - NEXTOSXVER=10.6 CUROSXVER=10.5 for HOST in powerpc-apple-darwin9 i386-apple-darwin9; do genbuild done libbuild @@ -88,11 +87,10 @@ ARCHLIST="" DLIB="" DARCHLIST="" OSX=Snowleopard PKTARGETOS=3 - NEXTOSXVER=10.7 CUROSXVER=10.6 for HOST in i386-apple-darwin10 x86_64-apple-darwin10; do genbuild done libbuild @@ -108,51 +106,48 @@ ARCHLIST="" DLIB="" DARCHLIST="" OSX=Lion PKTARGETOS=3 - NEXTOSXVER=10.8 CUROSXVER=10.7 for HOST in i386-apple-darwin11 x86_64-apple-darwin11; do genbuild done libbuild pkgbuild } # Build function for Snow Leopard/Lion/Mountain Lion -sltoml() { +sltomav() { makedir HEADERS=/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/PCSC.framework/Versions/A/Headers/ LIBRARY=/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/PCSC.framework/PCSC LIB="" ARCHLIST="" DLIB="" DARCHLIST="" - OSX=Sltoml + OSX=Sltomav PKTARGETOS=3 - NEXTOSXVER=10.9 CUROSXVER=10.6 for HOST in i386-apple-darwin10 x86_64-apple-darwin10; do genbuild done libbuild pkgbuild } # Build function for Snow Leopard/Lion/Mountain Lion -sltoml() { +sltomav() { makedir HEADERS=/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/PCSC.framework/Versions/A/Headers/ LIBRARY=/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/PCSC.framework/PCSC LIB="" ARCHLIST="" DLIB="" DARCHLIST="" - OSX=Sltoml + OSX=Sltomav PKTARGETOS=3 - NEXTOSXVER=10.9 CUROSXVER=10.6 for HOST in i386-apple-darwin10 x86_64-apple-darwin10; do genbuild done libbuild @@ -225,11 +220,10 @@ mkdir -p build/cackey_osx_build/${OSX}_pmbuild.pmdoc sed "s|@@BUILDROOTDIR@@|$(pwd)|g" build/cackey_osx_build/Template_pmbuild/${PMDOC}.in > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} sed "s|@@OSXVERSION@@|${OSX}|g" build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 sed "s|@@UUID@@|${UUID}|g" build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} sed "s|@@TARGETOS@@|${PKTARGETOS}|g" build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 - sed "s|@@NEXTOSXVER@@|${NEXTOSXVER}|g" build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} sed "s|@@CUROSXVER@@|${CUROSXVER}|g" build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 sed "s|@@LIBCACKEYG@@|${LIBCACKEYG}|g" build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} cp build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 mv build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC}.1 build/cackey_osx_build/${OSX}_pmbuild.pmdoc/${PMDOC} done @@ -236,12 +230,12 @@ EXT=pkg if [ ${OSX} == "Snowleopard" ]; then cat build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml | sed 's|for Mac OS X Snowleopard|for Mac OS X SnowLeopard|g' > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml.new mv build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml.new build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml fi - if [ ${OSX} == "Sltoml" ]; then - cat build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml | sed 's|for Mac OS X Sltoml|for Mac OS X SLtoML|g' > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml.new + if [ ${OSX} == "Sltomav" ]; then + cat build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml | sed 's|for Mac OS X Sltomav|for Mac OS X SLtoMav|g' > build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml.new mv build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml.new build/cackey_osx_build/${OSX}_pmbuild.pmdoc/index.xml fi /Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker -d build/cackey_osx_build/${OSX}_pmbuild.pmdoc -o macbuild/pkg/CACKey_${CACKEY_VERSION}_${OSX}.${EXT} tar --create --directory macbuild/pkg/ --file macbuild/pkg/CACKey_${CACKEY_VERSION}_${OSX}.${EXT}.tar CACKey_${CACKEY_VERSION}_${OSX}.${EXT} gzip -9 macbuild/pkg/CACKey_${CACKEY_VERSION}_${OSX}.${EXT}.tar @@ -274,20 +268,20 @@ ./autogen.sh lion exit $? ;; - "sltoml") + "sltomav") ./autogen.sh - sltoml + sltomav exit $? ;; "all") ./autogen.sh leopard - sltoml + sltomav echo "" echo "All builds complete." exit $? ;; Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -1115,31 +1115,32 @@ SCardDisconnect(slot->pcsc_card, SCARD_LEAVE_CARD); } slot->slot_reset = 1; slot->pcsc_card_connected = 0; - slot->token_flags = CKF_LOGIN_REQUIRED; + if (cackey_pin_command == NULL) { + slot->token_flags = CKF_LOGIN_REQUIRED; + } else { + slot->token_flags = 0; + } CACKEY_DEBUG_PRINTF("Returning."); return; } /* * SYNPOSIS - * LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol, LPDWORD selected_protocol); + * LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol); * * ARGUMENTS * cackey_slot *slot * Slot to send commands to * * DWORD default_protocol * Protocol to attempt first * - * LPDWORD selected_protocol - * [OUT] Protocol selected - * * RETURN VALUE * The return value from SCardReconnect() * * NOTES * This function is a wrapper around SCardReconnect() @@ -1148,24 +1149,31 @@ * dwPreferredProtocols of "default_protocol". If that call returns * SCARD_E_PROTO_MISMATCH try again with a protocol of T=0, and failing * that T=1. * */ -static LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol, LPDWORD selected_protocol) { +static LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol) { + DWORD selected_protocol; LONG scard_conn_ret; - scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, default_protocol, SCARD_RESET_CARD, selected_protocol); + selected_protocol = 0; + + scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, default_protocol, SCARD_RESET_CARD, &selected_protocol); if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) { CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0") - scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, selected_protocol); + scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &selected_protocol); if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) { CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1") - scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_RESET_CARD, selected_protocol); + scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &selected_protocol); } } + + if (scard_conn_ret == SCARD_S_SUCCESS) { + slot->protocol = selected_protocol; + } return(scard_conn_ret); } /* @@ -1232,11 +1240,11 @@ CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1") scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol); } } - scard_conn_ret = cackey_reconnect_card(slot, protocol, &protocol); + scard_conn_ret = cackey_reconnect_card(slot, protocol); } if (scard_conn_ret != SCARD_S_SUCCESS) { CACKEY_DEBUG_PRINTF("Connection to card failed, returning in failure (SCardConnect() = %s/%li)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_conn_ret), (long) scard_conn_ret); @@ -1439,11 +1447,10 @@ */ static cackey_ret cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned int lc, unsigned char *data, unsigned int le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len) { uint8_t major_rc, minor_rc; size_t bytes_to_copy, tmp_respdata_len; LPCSCARD_IO_REQUEST pioSendPci; - DWORD protocol; DWORD xmit_len, recv_len; LONG scard_xmit_ret, scard_reconn_ret; BYTE xmit_buf[1024], recv_buf[1024]; int pcsc_connect_ret, pcsc_getresp_ret; int idx; @@ -1534,10 +1541,12 @@ CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx), will ask calling function to retry (not resetting card)...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret); /* Begin Smartcard Transaction */ cackey_end_transaction(slot); + cackey_reconnect_card(slot, slot->protocol); + return(CACKEY_PCSC_E_RETRY); } 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); @@ -1546,15 +1555,13 @@ cackey_mark_slot_reset(slot); if (scard_xmit_ret == SCARD_W_RESET_CARD) { CACKEY_DEBUG_PRINTF("Reset required, please hold..."); - scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &protocol); + scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1); if (scard_reconn_ret == SCARD_S_SUCCESS) { - /* Update protocol */ - slot->protocol = protocol; switch (slot->protocol) { case SCARD_PROTOCOL_T0: pioSendPci = SCARD_PCI_T0; break; @@ -2855,35 +2862,35 @@ case CACKEY_ID_TYPE_CERT_ONLY: break; } if (send_ret != CACKEY_PCSC_S_OK) { - CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error."); - if (free_tmpbuf) { if (tmpbuf_s) { free(tmpbuf_s); } } /* End transaction */ cackey_end_transaction(slot); + if (send_ret == CACKEY_PCSC_E_RETRY) { + CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- retrying."); + + return(cackey_signdecrypt(slot, identity, buf, buflen, outbuf, outbuflen, padInput, unpadOutput)); + } + + CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error."); + if (respcode == 0x6982 || respcode == 0x6e00) { - CACKEY_DEBUG_PRINTF("Security status not satisified (respcode = 0x%04x). Returning NEEDLOGIN", (int) respcode); + if (respcode == 0x6E00) { + CACKEY_DEBUG_PRINTF("Got \"WRONG CLASS\", this means we are talking to the wrong object (likely because the card went away) -- resetting"); + } else { + CACKEY_DEBUG_PRINTF("Security status not satisified (respcode = 0x%04x). Returning NEEDLOGIN", (int) respcode); + } cackey_mark_slot_reset(slot); - slot->token_flags = CKF_LOGIN_REQUIRED; - - return(CACKEY_PCSC_E_NEEDLOGIN); - } - - if (respcode == 0x6E00) { - CACKEY_DEBUG_PRINTF("Got \"WRONG CLASS\", this means we are talking to the wrong object (likely because the card went away) -- resetting"); - - cackey_mark_slot_reset(slot); - slot->token_flags = CKF_LOGIN_REQUIRED; return(CACKEY_PCSC_E_NEEDLOGIN); } if (send_ret == CACKEY_PCSC_E_TOKENABSENT) { @@ -3184,15 +3191,12 @@ cackey_mark_slot_reset(slot); if (status_ret == SCARD_W_RESET_CARD) { CACKEY_DEBUG_PRINTF("Reset required, please hold..."); - scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &protocol); + scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1); if (scard_reconn_ret == SCARD_S_SUCCESS) { - /* Update protocol */ - slot->protocol = protocol; - /* Re-establish transaction, if it was present */ if (slot->transaction_depth > 0) { slot->transaction_depth--; slot->transaction_need_hw_lock = 1; cackey_begin_transaction(slot); @@ -4432,11 +4436,11 @@ CACKEY_DEBUG_PRINTF("Found more readers than slots are available!"); break; } - CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers); + CACKEY_DEBUG_PRINTF("Found reader: %s (currslot = %lu)", pcsc_readers, (unsigned long) currslot); /* Only update the list of slots if we are actually being asked supply the slot information */ if (pSlotList) { if (slot_reset) { cackey_slots[currslot].active = 1; @@ -4443,27 +4447,35 @@ cackey_slots[currslot].internal = 0; cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers); cackey_slots[currslot].pcsc_card_connected = 0; cackey_slots[currslot].transaction_depth = 0; cackey_slots[currslot].transaction_need_hw_lock = 0; - cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED; + if (cackey_pin_command == NULL) { + cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED; + } else { + cackey_slots[currslot].token_flags = 0; + } cackey_slots[currslot].label = NULL; cackey_mark_slot_reset(&cackey_slots[currslot]); } } else { - /* Artificially increase the number of active slots by what will become active */ - slot_count++; + if (!cackey_slots[currslot].active) { + /* Artificially increase the number of active slots by what will become active */ + CACKEY_DEBUG_PRINTF("Found in-active slot %lu, but it will be active after a reset -- marking as active for accounting purposes", (unsigned long) currslot); + + slot_count++; + } } currslot++; pcsc_readers += curr_reader_len + 1; } for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) { if (cackey_slots[currslot].active) { - CACKEY_DEBUG_PRINTF("Found active slot %lu", (unsigned long) currslot); + CACKEY_DEBUG_PRINTF("Found active slot %lu, reader = %s", (unsigned long) currslot, cackey_slots[currslot].pcsc_reader); slot_count++; } } } else { @@ -5188,11 +5200,11 @@ CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED); 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_DEFINE_FUNCTION(CK_RV, _C_LoginMutexArg)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, int lock_mutex) { CK_SLOT_ID slotID; FILE *pinfd; char *pincmd, pinbuf[64], *fgets_ret; int mutex_retval; int tries_remaining; @@ -5217,19 +5229,23 @@ CACKEY_DEBUG_PRINTF("Error. We only support USER mode, asked for %lu mode.", (unsigned long) userType) return(CKR_USER_TYPE_INVALID); } - mutex_retval = cackey_mutex_lock(cackey_biglock); - if (mutex_retval != 0) { - CACKEY_DEBUG_PRINTF("Error. Locking failed."); + if (lock_mutex) { + mutex_retval = cackey_mutex_lock(cackey_biglock); + if (mutex_retval != 0) { + CACKEY_DEBUG_PRINTF("Error. Locking failed."); - return(CKR_GENERAL_ERROR); + return(CKR_GENERAL_ERROR); + } } if (!cackey_sessions[hSession].active) { - cackey_mutex_unlock(cackey_biglock); + if (lock_mutex) { + cackey_mutex_unlock(cackey_biglock); + } CACKEY_DEBUG_PRINTF("Error. Session not active."); return(CKR_SESSION_HANDLE_INVALID); } @@ -5236,18 +5252,24 @@ 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); + + if (lock_mutex) { + cackey_mutex_unlock(cackey_biglock); + } 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); + if (lock_mutex) { + cackey_mutex_unlock(cackey_biglock); + } return(CKR_GENERAL_ERROR); } pincmd = cackey_pin_command; @@ -5260,11 +5282,13 @@ pinfd = popen(pincmd, "r"); if (pinfd == NULL) { CACKEY_DEBUG_PRINTF("Error. %s: Unable to run", pincmd); - cackey_mutex_unlock(cackey_biglock); + if (lock_mutex) { + cackey_mutex_unlock(cackey_biglock); + } CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT); return(CKR_PIN_INCORRECT); } @@ -5276,21 +5300,25 @@ pclose_ret = pclose(pinfd); if (pclose_ret != 0) { CACKEY_DEBUG_PRINTF("Error. %s: exited with non-zero status of %i", pincmd, pclose_ret); - cackey_mutex_unlock(cackey_biglock); + if (lock_mutex) { + cackey_mutex_unlock(cackey_biglock); + } CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT); return(CKR_PIN_INCORRECT); } if (strlen(pinbuf) < 1) { CACKEY_DEBUG_PRINTF("Error. %s: returned no data", pincmd); - cackey_mutex_unlock(cackey_biglock); + if (lock_mutex) { + cackey_mutex_unlock(cackey_biglock); + } CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT); return(CKR_PIN_INCORRECT); } @@ -5303,11 +5331,13 @@ ulPinLen = strlen(pinbuf); } login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining); if (login_ret != CACKEY_PCSC_S_OK) { - cackey_mutex_unlock(cackey_biglock); + if (lock_mutex) { + cackey_mutex_unlock(cackey_biglock); + } if (login_ret == CACKEY_PCSC_E_LOCKED) { CACKEY_DEBUG_PRINTF("Error. Token is locked."); cackey_slots[slotID].token_flags |= CKF_USER_PIN_LOCKED; @@ -5336,21 +5366,27 @@ 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) { - CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); + if (lock_mutex) { + mutex_retval = cackey_mutex_unlock(cackey_biglock); + if (mutex_retval != 0) { + CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); - return(CKR_GENERAL_ERROR); + return(CKR_GENERAL_ERROR); + } } CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK); return(CKR_OK); } + +CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { + return(_C_LoginMutexArg(hSession, userType, pPin, ulPinLen, 1)); +} CK_DEFINE_FUNCTION(CK_RV, C_Logout)(CK_SESSION_HANDLE hSession) { CK_SLOT_ID slotID; int mutex_retval; @@ -5398,11 +5434,16 @@ return(CKR_GENERAL_ERROR); } cackey_sessions[hSession].state = CKS_RO_PUBLIC_SESSION; - cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED; + + if (cackey_pin_command == NULL) { + cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED; + } else { + cackey_slots[slotID].token_flags = 0; + } mutex_retval = cackey_mutex_unlock(cackey_biglock); if (mutex_retval != 0) { CACKEY_DEBUG_PRINTF("Error. Unlocking failed."); @@ -6322,18 +6363,26 @@ switch (cackey_sessions[hSession].decrypt_mechanism) { case CKM_RSA_PKCS: /* Ask card to decrypt */ buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1); + + if (buflen == CACKEY_PCSC_E_NEEDLOGIN && cackey_pin_command != NULL) { + if (_C_LoginMutexArg(hSession, CKU_USER, NULL, 0, 0) == CKR_OK) { + buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1); + } + } if (buflen < 0) { /* Decryption failed. */ if (buflen == CACKEY_PCSC_E_NEEDLOGIN) { retval = CKR_USER_NOT_LOGGED_IN; } else if (buflen == CACKEY_PCSC_E_TOKENABSENT) { retval = CKR_DEVICE_REMOVED; } else { + CACKEY_DEBUG_PRINTF("Failed to send APDU, error = %li", (long int) buflen); + retval = CKR_GENERAL_ERROR; } } else if (((unsigned long) buflen) > *pulPartLen && pPart) { /* Decrypted data too large */ retval = CKR_BUFFER_TOO_SMALL; @@ -6833,10 +6882,16 @@ 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", (void *) 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 == CACKEY_PCSC_E_NEEDLOGIN && cackey_pin_command != NULL) { + if (_C_LoginMutexArg(hSession, CKU_USER, NULL, 0, 0) == CKR_OK) { + 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. */ if (sigbuflen == CACKEY_PCSC_E_NEEDLOGIN) { retval = CKR_USER_NOT_LOGGED_IN; Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1,6 +1,6 @@ -AC_INIT(cackey, 0.6.8) +AC_INIT(cackey, 0.7.0) AC_CONFIG_HEADERS(config.h) dnl Locate standard tools AC_PROG_CC AC_PROG_MAKE_SET