bool PCSCReader::open( void) { // No valid context so we should leave ... if (0x00 == m_hScardContext) return false; long retValue = SCARD_S_SUCCESS; retValue = SCardReconnect(m_hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY, SCARD_LEAVE_CARD, &m_dwProtocol); #if !defined(__APPLE__) BYTE atr[512]; DWORD len = sizeof(atr); SCardGetAttrib(m_hCard, SCARD_ATTR_ATR_STRING, (LPBYTE) &atr, &len); #else unsigned char atr[512]; uint32_t len = sizeof(atr); char szReader[128]; uint32_t cch = 128; uint32_t dwState; uint32_t dwProtocol; SCardStatus(m_hCard, szReader, &cch, &dwState, &dwProtocol, (unsigned char *)&atr, &len); #endif return true; }
static void smartcard_check_status (SCARDCONTEXT hContext, const char* pReader, SCARDHANDLE hCardHandle, /* Can be 0 on the first call */ SCARDHANDLE* newCardHandle, /* The handle returned */ DWORD* pdwState) { DWORD shareMode = SCARD_SHARE_SHARED; DWORD preferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; DWORD dwAP; LONG result; if (hCardHandle == 0) { result = SCardConnect(hContext, pReader, shareMode, preferredProtocols, &hCardHandle, &dwAP); DEBUG_SCARD_STATUS("SCardConnect", result); if (SCARD_S_SUCCESS != result) { hCardHandle = 0; } } char szReader[200]; DWORD cch = sizeof(szReader); BYTE bAttr[32]; DWORD cByte = 32; size_t countStatusAttempts = 0; while (hCardHandle && (countStatusAttempts < 2)) { *pdwState = SCARD_UNKNOWN; result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte); DEBUG_SCARD_STATUS("SCardStatus", result); countStatusAttempts++; if ((SCARD_W_RESET_CARD == result) && (countStatusAttempts < 2)) { result = SCardReconnect(hCardHandle, shareMode, preferredProtocols, SCARD_RESET_CARD, &dwAP); DEBUG_SCARD_STATUS("SCardReconnect", result); if (SCARD_S_SUCCESS != result) { break; } } else { break; } } if (SCARD_S_SUCCESS != result) { if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { *pdwState = SCARD_ABSENT; } else { *pdwState = SCARD_UNKNOWN; } } if (newCardHandle == NULL) { result = SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); DEBUG_SCARD_STATUS("SCardDisconnect", result); } else { *newCardHandle = hCardHandle; } }
vector<BYTE> PCSCReader::getATRForPresentCard() { vector<BYTE> atr; if (0x00 == m_hCard) return atr; #if !defined(__APPLE__) DWORD atrSize; SCardGetAttrib(m_hCard, SCARD_ATTR_ATR_STRING, 0x00, &atrSize); atr.reserve(atrSize); atr.resize(atrSize); SCardGetAttrib(m_hCard, SCARD_ATTR_ATR_STRING, &atr[0], &atrSize); #else unsigned char atr_[512]; uint32_t len = sizeof(atr_); char szReader[128]; uint32_t cch = 128; uint32_t dwState; uint32_t dwProtocol; SCardStatus(m_hCard, szReader, &cch, &dwState, &dwProtocol, (unsigned char *)&atr_, &len); for (int i = 0; i < len; i++) atr.push_back(atr_[i]); #endif return atr; }
/* * Transmit. */ JNIEXPORT jint JNICALL GEN_FUNCNAME(Card_NativeStatus) (JNIEnv *env, jobject _this, jobject jrstate) { SCARDHANDLE card; char rdrname[256]; jbyteArray jatr; DWORD rdrlen = 256; DWORD pdwState; DWORD pdwProto; unsigned char pbAtr[64]; DWORD pcbAtrLen = 64; LONG rv; card = (SCARDHANDLE) (*env)->GetLongField(env, _this, CardField); rv = SCardStatus(card, &rdrname[0], &rdrlen, &pdwState, &pdwProto, &pbAtr[0], &pcbAtrLen); if (rv != SCARD_S_SUCCESS) { JPCSC_LOG(("NativeCardStatus(): error 0x%lx\n", rv)); return rv; } (*env)->SetIntField(env, jrstate, CurrentStateField, pdwState); (*env)->SetIntField(env, jrstate, ProtoStateField, pdwProto); (*env)->SetObjectField(env, jrstate, ReaderStateField, (*env)->NewStringUTF(env, rdrname)); jatr = (*env)->NewByteArray(env, pcbAtrLen); (*env)->SetByteArrayRegion(env, jatr, 0, pcbAtrLen, pbAtr); (*env)->SetObjectField(env, jrstate, AtrStateField, jatr); return rv; }
/* * Begin transaction. */ JNIEXPORT jint JNICALL GEN_FUNCNAME(Card_NativeBeginTransaction) (JNIEnv *env, jobject _this) { SCARDHANDLE card; LONG rv; card = (SCARDHANDLE) (*env)->GetLongField(env, _this, CardField); rv = SCardBeginTransaction(card); #ifdef WIN32 /* Handle MS Resouce Manager bug on Win9x/Me/NT4/Winxpsp1 http://support.microsoft.com/default.aspx?scid=kb;en-us;230031 */ if (rv == SCARD_S_SUCCESS) { char rdrname[256]; DWORD rdrlen = 256; DWORD pdwState; DWORD pdwProto; char pbAtr[64]; DWORD pcbAtrLen = 64; /* verify card handle not reset */ rv = SCardStatus(card, &rdrname[0], &rdrlen, &pdwState, &pdwProto, &pbAtr[0], &pcbAtrLen); if (rv == SCARD_S_SUCCESS && pdwState < SCARD_NEGOTIABLE) rv = SCARD_W_RESET_CARD; } #endif /* WIN32 */ return rv; }
static int32_t pcsc_check_card_inserted(struct s_reader *pcsc_reader) { struct pcsc_data *crdr_data = pcsc_reader->crdr_data; DWORD dwState, dwAtrLen, dwReaderLen; unsigned char pbAtr[64]; SCARDHANDLE rv; dwAtrLen = sizeof(pbAtr); rv=0; dwState=0; dwReaderLen=0; // Do we have a card ? if (!crdr_data->pcsc_has_card && !crdr_data->hCard) { // try connecting to the card rv = SCardConnect(crdr_data->hContext, crdr_data->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &crdr_data->hCard, &crdr_data->dwActiveProtocol); if (rv == (LONG)SCARD_E_NO_SMARTCARD) { // no card in pcsc_reader crdr_data->pcsc_has_card=0; if(crdr_data->hCard) { SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD); crdr_data->hCard=0; } // rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv ); return OK; } else if (rv == (LONG)SCARD_W_UNRESPONSIVE_CARD) { // there is a problem with the card in the pcsc_reader crdr_data->pcsc_has_card=0; crdr_data->hCard=0; rdr_log(pcsc_reader, "PCSC card in %s is unresponsive. Eject and re-insert please.", crdr_data->pcsc_name); return ERROR; } else if( rv == SCARD_S_SUCCESS ) { // we have a card crdr_data->pcsc_has_card=1; rdr_log(pcsc_reader, "PCSC was opened with handle: %ld", (long)crdr_data->hCard); } else { // if we get here we have a bigger problem -> display status and debug // rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %s status [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv ); return ERROR; } } // if we get there the card is ready, check its status rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen); if (rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED ) )) { return OK; } else { SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD); crdr_data->hCard = 0; crdr_data->pcsc_has_card = 0; } return ERROR; }
void testStatus(SCARDCONTEXT* phContext) { wchar_t szReaderName[1024]; DWORD dwReaderLen = 1024; DWORD dwState; DWORD dwProtocol; BYTE bAttribute[32]; DWORD dwAtrLen; BYTE pbRecvBuffer[200]; DWORD dwRecvLength, dwReturn; dwReturn = SCardControl(*phContext, SCARD_CTL_CODE(3400), NULL, 0, pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength); SCardStatus( *phContext, szReaderName, &dwReaderLen, &dwState, &dwProtocol, &bAttribute[0], &dwAtrLen ); }
static const bytestring_t* pcsc_last_atr(cardreader_t* cr) { pcsc_data_t* pcsc = cr->extra_data; DWORD state; DWORD protocol; BYTE pbAtr[MAX_ATR_SIZE]; DWORD atrlen=MAX_ATR_SIZE; char readername[MAX_READERNAME]; DWORD readernamelen=MAX_READERNAME; /*char *tmp;*/ pcsc->status = SCardStatus(pcsc->hcard, readername,&readernamelen, &state, &protocol, pbAtr,&atrlen); if (pcsc->status==SCARD_S_SUCCESS) { bytestring_assign_data(cr->atr,atrlen,pbAtr); /*tmp = bytestring_to_format("%D",cr->atr); log_printf(LOG_INFO,"ATR is %i bytes: %s",atrlen,tmp); free(tmp);*/ } else { bytestring_clear(cr->atr); log_printf(LOG_ERROR,"Failed to query card status: %s (error 0x%08x).", pcsc_stringify_error(pcsc->status), pcsc->status ); } return cr->atr; }
int32_t pcsc_check_card_inserted(struct s_reader *pcsc_reader) { DWORD dwState, dwAtrLen, dwReaderLen; BYTE pbAtr[64]; LONG rv; dwAtrLen = sizeof(pbAtr); rv=0; dwState=0; dwReaderLen=0; // Do we have a card ? if (!pcsc_reader->pcsc_has_card && !(SCARDHANDLE)(pcsc_reader->hCard)) { // try connecting to the card rv = SCardConnect(pcsc_reader->hContext, pcsc_reader->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &pcsc_reader->hCard, &pcsc_reader->dwActiveProtocol); if (rv==SCARD_E_NO_SMARTCARD) { // no card in pcsc_reader pcsc_reader->pcsc_has_card=0; if((SCARDHANDLE)(pcsc_reader->hCard)) { SCardDisconnect((SCARDHANDLE)(pcsc_reader->hCard),SCARD_RESET_CARD); pcsc_reader->hCard=0; } // rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, (unsigned long)rv ); return 0; } else if( rv == SCARD_W_UNRESPONSIVE_CARD ) { // there is a problem with the card in the pcsc_reader pcsc_reader->pcsc_has_card=0; pcsc_reader->hCard=0; rdr_log(pcsc_reader, "PCSC card in %s is unresponsive. Eject and re-insert please.", pcsc_reader->pcsc_name); return 0; } else if( rv == SCARD_S_SUCCESS ) { // we have a card pcsc_reader->pcsc_has_card=1; } else { // if we get here we have a bigger problem -> display status and debug // rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %s status [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, (unsigned long)rv ); return 0; } } // if we get there the card is ready, check its status rv = SCardStatus((SCARDHANDLE)(pcsc_reader->hCard), NULL, &dwReaderLen, &dwState, &pcsc_reader->dwActiveProtocol, pbAtr, &dwAtrLen); if (rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED ) )) { return CARD_INSERTED; } else { SCardDisconnect((SCARDHANDLE)(pcsc_reader->hCard),SCARD_RESET_CARD); pcsc_reader->hCard=0; pcsc_reader->pcsc_has_card=0; } return 0; }
testA(int argc,char** argv ) { int i; myprintf("=============================\n"); myprintf("Part A: Checking card monitor\n"); myprintf("=============================\n"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_UNAWARE; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); if( (rgReaderStates[0])->dwEventState & SCARD_STATE_PRESENT ) { myprintf("<< Please remove smart card \n"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); } printit("1.Please insert smart card"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); myprintf("Passed\n"); printit("2. IOCTL_SMARTCARD_IS_PRESENT"); myprintf("Passed\n"); printit("3. Please remove smart card "); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); if( rv != SCARD_S_SUCCESS ) return -1; if( (rgReaderStates[0])->dwEventState & SCARD_STATE_EMPTY) myprintf("Passed\n"); else myprintf("Failed \n"); printit("4. IOCTL_SMARTCARD_IS_ABSENT"); myprintf("Passed\n"); printit("5. Insert and remove a smart card repeatedly"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY; for(i=0;i<10;i++) { rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); (rgReaderStates[0])->dwCurrentState = (rgReaderStates[0])->dwEventState; } myprintf("Passed \n"); if( more_details ) { rv = SCardConnect(hContext, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0| SCARD_PROTOCOL_T1, &hCard, &dwPref); if ( rv != SCARD_S_SUCCESS ) { SCardReleaseContext( hContext ); return 0; } readerlen=100; rv = SCardStatus(hCard,readerName,&readerlen,&readerstate,&protocol,r,&atrlen); if( rv != SCARD_S_SUCCESS ) { return -1; } myprintf("ATR :"); for(i=0;i<atrlen;i++) { myprintf("%0x ",r[i]); } myprintf("\n"); myprintf("Powered up successfully \n"); } return 0; }
int get_card_state(SCARDHANDLE card, struct card_state *cst) { char *reader_names = NULL; size_t reader_names_size = 0; int rc; cst->atr = NULL; cst->atr_len = SCARD_AUTOALLOCATE; return SCardStatus(card, NULL, &reader_names_size, &cst->state, &cst->proto, (char *) &cst->atr, &cst->atr_len); }
bool Token::checkATR(){ LONG lReturn; char szReader[200]; DWORD cch = 200; DWORD dwState, dwProtocol; lReturn = SCardStatus(hCardHandle, szReader, &cch, &dwState, &dwProtocol, (LPBYTE)&(this->ATR), &(this->lATR)); if (this->lATR == laladdinATR && memcmp(this->ATR, aladdinATR, this->lATR) == 0){ return true; } else { return false; } }
static void smartcard_check_status (SCARDCONTEXT hContext, const char* pReader, SCARDHANDLE hCardHandle, /* Can be 0 on the first call */ SCARDHANDLE* newCardHandle, /* The handle returned */ DWORD* pdwState) { if (hCardHandle == 0) { DWORD dwAP; LONG result = SCardConnect(hContext, pReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCardHandle, &dwAP); if (SCARD_S_SUCCESS != result) { hCardHandle = 0; if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { *pdwState = SCARD_ABSENT; } else { *pdwState = SCARD_UNKNOWN; } if (newCardHandle == NULL) { (void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); hCardHandle = 0; } else { *newCardHandle = hCardHandle; } } } char szReader[200]; DWORD cch = sizeof(szReader); BYTE bAttr[32]; DWORD cByte = 32; LONG result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte); if (SCARD_S_SUCCESS != result) { if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { *pdwState = SCARD_ABSENT; } else { *pdwState = SCARD_UNKNOWN; } } if (newCardHandle == NULL) { (void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); hCardHandle = 0; } else { *newCardHandle = hCardHandle; } }
/** * checkForRemovedPCSCToken looks into a specific slot for a removed token. * * @param slot Pointer to slot structure. * * @return * <P><TABLE> * <TR><TD>Code</TD><TD>Meaning</TD></TR> * <TR> * <TD>CKR_OK </TD> * <TD>Success </TD> * </TR> * <TR> * <TD>CKR_HOST_MEMORY </TD> * <TD>Error getting memory (malloc) </TD> * </TR> * <TR> * <TD>CKR_GENERAL_ERROR </TD> * <TD>Error opening slot directory </TD> * </TR> * </TABLE></P> */ static int checkForRemovedPCSCToken(struct p11Slot_t *slot) { int rc; LONG rv; FUNC_CALLED(); if (slot->closed) { FUNC_RETURNS(CKR_TOKEN_NOT_PRESENT); } if (!slot->card) { FUNC_RETURNS(CKR_TOKEN_NOT_PRESENT); } rv = SCardStatus(slot->card, NULL, 0, 0, 0, 0, 0); #ifdef DEBUG debug("SCardStatus: %s\n", pcsc_error_to_string(rv)); #endif if (rv == SCARD_S_SUCCESS) { FUNC_RETURNS(CKR_OK); } else if ((rv == SCARD_W_REMOVED_CARD) || (rv == SCARD_E_INVALID_HANDLE) || (rv == SCARD_E_READER_UNAVAILABLE)) { rc = removeToken(slot); if (rc != CKR_OK) { FUNC_RETURNS(rc); } rc = SCardDisconnect(slot->card, SCARD_UNPOWER_CARD); #ifdef DEBUG debug("SCardDisconnect (%i, %s): %s\n", slot->id, slot->readername, pcsc_error_to_string(rc)); #endif // Check if a new token was inserted in the meantime rc = checkForNewPCSCToken(slot); if (rc == CKR_TOKEN_NOT_PRESENT) { FUNC_RETURNS(CKR_DEVICE_REMOVED); } } else { FUNC_FAILS(CKR_DEVICE_ERROR, "Error getting PC/SC card terminal status"); } FUNC_RETURNS(rc); }
static int32_t pcsc_activate_card(struct s_reader *pcsc_reader, uchar *atr, uint16_t *atr_size) { struct pcsc_data *crdr_data = pcsc_reader->crdr_data; LONG rv; DWORD dwState, dwAtrLen, dwReaderLen; unsigned char pbAtr[ATR_MAX_SIZE]; char tmp[sizeof(pbAtr) * 3 + 1]; rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC initializing card in (%s)", crdr_data->pcsc_name); dwAtrLen = sizeof(pbAtr); dwReaderLen = 0; rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting card in (%s) with handle %ld", crdr_data->pcsc_name, (long)(crdr_data->hCard)); rv = SCardReconnect(crdr_data->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &crdr_data->dwActiveProtocol); if(rv != SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to reset card (%lx)", (unsigned long)rv); return ERROR; } rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting done on card in (%s)", crdr_data->pcsc_name); rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1)); rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC getting ATR for card in (%s)", crdr_data->pcsc_name); rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen); if(rv == SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1)); memcpy(atr, pbAtr, dwAtrLen); *atr_size = dwAtrLen; rdr_log(pcsc_reader, "ATR: %s", cs_hexdump(1, (uchar *)pbAtr, dwAtrLen, tmp, sizeof(tmp))); memcpy(pcsc_reader->card_atr, pbAtr, dwAtrLen); pcsc_reader->card_atr_length = dwAtrLen; return OK; } else { rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to get ATR for card (%lx)", (unsigned long)rv); } return ERROR; }
bool silvia_pcsc_card::status() { if (!connected) return false; DWORD active_protocol; DWORD state; DWORD atr_len = MAX_ATR_SIZE; DWORD reader_len = 0; BYTE atr[MAX_ATR_SIZE]; LONG rv = SCardStatus(card_handle, NULL, &reader_len, &state, &active_protocol, atr, &atr_len); connected = (rv == SCARD_S_SUCCESS) && (FLAG_SET(state, SCARD_PRESENT)); if (!connected) { SCardDisconnect(card_handle, SCARD_UNPOWER_CARD); } return connected; }
void testGetATR_2(SCARDHANDLE* phCard) { WCHAR readerName[256]; DWORD readerNameLen = 256; BYTE pbAtr[32]; DWORD dwLen = 32; DWORD dwState; DWORD dwProtocol; DWORD retval; retval = SCardStatus(*phCard, readerName, &readerNameLen, &dwState, &dwProtocol, pbAtr, &dwLen); printf ("trying to get the card's ATR by calling SCardStatus\n"); printf ("returned: ATR length = %d retval: 0x%08x\n",dwLen, retval); printf ("ATR = "); for(int i = 0; i < dwLen; i++) { printf(" 0x%02x",pbAtr[i]); } printf ("\n"); }
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv) { SCARDHANDLE hCard; SCARDCONTEXT hContext; SCARD_READERSTATE_A rgReaderStates[1]; DWORD dwReaderLen, dwState, dwProt, dwAtrLen; DWORD dwPref, dwReaders = 0; char *pcReaders = NULL, *mszReaders; #ifdef USE_AUTOALLOCATE unsigned char *pbAtr = NULL; #else unsigned char pbAtr[MAX_ATR_SIZE]; #endif union { unsigned char as_char[100]; DWORD as_DWORD; uint32_t as_uint32_t; } buf; DWORD dwBufLen; unsigned char *pbAttr = NULL; DWORD pcbAttrLen; char *mszGroups; DWORD dwGroups = 0; long rv; DWORD i; int p, iReader; int iList[16]; SCARD_IO_REQUEST pioRecvPci; SCARD_IO_REQUEST pioSendPci; unsigned char bSendBuffer[MAX_BUFFER_SIZE]; unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; DWORD send_length, length; (void)argc; (void)argv; printf("\nMUSCLE PC/SC Lite unitary test Program\n\n"); printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n"); printf("Do NOT use it unless you really know what you do.\n\n" NORMAL); printf("Testing SCardEstablishContext\t: "); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext+1); test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardListReaderGroups\t: "); #ifdef USE_AUTOALLOCATE dwGroups = SCARD_AUTOALLOCATE; rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups); #else rv = SCardListReaderGroups(hContext, NULL, &dwGroups); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaderGroups\t: "); mszGroups = calloc(dwGroups, sizeof(char)); rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups); #endif test_rv(rv, hContext, PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwGroups; i++) { ++p; printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]); while (mszGroups[++i] != 0) ; } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, mszGroups); test_rv(rv, hContext, PANIC); #else free(mszGroups); #endif wait_for_card_again: mszGroups = NULL; printf("Testing SCardListReaders\t: "); rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, DONT_PANIC); if (SCARD_E_NO_READERS_AVAILABLE == rv) { printf("Testing SCardGetStatusChange \n"); printf("Please insert a working reader\t: "); (void)fflush(stdout); rgReaderStates[0].szReader = "\\\\?PnP?\\Notification"; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); } printf("Testing SCardListReaders\t: "); #ifdef USE_AUTOALLOCATE dwReaders = SCARD_AUTOALLOCATE; rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders); #else rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaders\t: "); mszReaders = calloc(dwReaders, sizeof(char)); rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders); #endif test_rv(rv, hContext, DONT_PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwReaders; i++) { ++p; printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]); iList[p] = i; while (mszReaders[++i] != 0) ; } if (p > 1) do { char input[80]; printf("Enter the reader number\t\t: "); (void)fgets(input, sizeof(input), stdin); (void)sscanf(input, "%d", &iReader); if (iReader > p || iReader <= 0) printf("Invalid Value - try again\n"); } while (iReader > p || iReader <= 0); else iReader = 1; rgReaderStates[0].szReader = &mszReaders[iList[iReader]]; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; printf("Waiting for card insertion\t: "); (void)fflush(stdout); rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN) { printf("\nA reader has been connected/disconnected\n"); goto wait_for_card_again; } printf("Testing SCardConnect\t\t: "); rv = SCardConnect(hContext, &mszReaders[iList[iReader]], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwPref); test_rv(rv, hContext, PANIC); switch(dwPref) { case SCARD_PROTOCOL_T0: pioSendPci = *SCARD_PCI_T0; break; case SCARD_PROTOCOL_T1: pioSendPci = *SCARD_PCI_T1; break; case SCARD_PROTOCOL_RAW: pioSendPci = *SCARD_PCI_RAW; break; default: printf("Unknown protocol\n"); return -1; } int bBreak = 0; while (1) { char inputCommand[1024]; char inputAPDU[1024]; int inputAPDULen = sizeof(inputAPDU); printf("Enter APDU to send, (e.g. 00:A4:04:00:00)\n"); printf("Command APDU: "); (void)fgets(inputCommand, sizeof(inputCommand), stdin); int stringlen = strlen(inputCommand); if( inputCommand[stringlen-1] == '\n' ) { inputCommand[stringlen-1] = 0; } //remove newline int bError = sc_hex_to_bin(inputCommand, inputAPDU, &inputAPDULen); //printf("debug - value bError: %i\n",bError); if (bError) { printf("Error parsing input\n\n"); continue; } send_length = inputAPDULen; if (inputAPDULen == 0) { break; } printf("debug inputAPDULen: %i\n",inputAPDULen); memcpy(bSendBuffer, inputAPDU, send_length); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit:\n "); printf("-> "); for (i=0; i<send_length; i++) { printf(" %02X", bSendBuffer[i]); } printf("\n"); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf("<- " GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); } testrun(&hCard, &hContext, &pioSendPci, 0); testrun(&hCard, &hContext, &pioSendPci, 1); testrun(&hCard, &hContext, &pioSendPci, 2); testrun(&hCard, &hContext, &pioSendPci, 3); printf("Testing SCardControl\t\t: "); #ifdef PCSC_PRE_120 { char buffer[1024] = "Foobar"; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength); } #else { char buffer[1024] = { 0x02 }; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer, sizeof(buffer), &cbRecvLength); if (cbRecvLength && (SCARD_S_SUCCESS == rv)) { for (i=0; i<cbRecvLength; i++) printf("%c", buffer[i]); printf(" "); } } #endif test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); printf("SCARD_ATTR_ATR_STRING: " GREEN); for (i = 0; i < pcbAttrLen; i++) printf("%02X ", pbAttr[i]); printf("\n" NORMAL); } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("Vendor IFD version\t\t: " GREEN "0x%08lX\n" NORMAL, buf.as_DWORD); printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { if (dwBufLen == sizeof(uint32_t)) printf("Max message length\t\t: " GREEN "%d\n" NORMAL, buf.as_uint32_t); else printf(RED "Wrong size" NORMAL); } printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char); printf("Testing SCardSetAttrib\t\t: "); rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1); test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardStatus\t\t: "); #ifdef USE_AUTOALLOCATE dwReaderLen = SCARD_AUTOALLOCATE; dwAtrLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR)&pcReaders, &dwReaderLen, &dwState, &dwProt, (LPBYTE)&pbAtr, &dwAtrLen); #else dwReaderLen = 100; pcReaders = malloc(sizeof(char) * 100); dwAtrLen = MAX_ATR_SIZE; rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt, pbAtr, &dwAtrLen); #endif test_rv(rv, hContext, PANIC); printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReaders); printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState); printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1); printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n", dwAtrLen); printf("Current Reader ATR Value\t: " GREEN); for (i = 0; i < dwAtrLen; i++) { printf("%02X ", pbAtr[i]); } printf(NORMAL "\n"); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pcReaders); test_rv(rv, hContext, PANIC); printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAtr); test_rv(rv, hContext, PANIC); #else if (pcReaders) free(pcReaders); #endif if (rv != SCARD_S_SUCCESS) { (void)SCardDisconnect(hCard, SCARD_RESET_CARD); (void)SCardReleaseContext(hContext); } printf("Press enter: "); (void)getchar(); printf("Testing SCardReconnect\t\t: "); rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD, &dwPref); test_rv(rv, hContext, PANIC); printf("Testing SCardDisconnect\t\t: "); rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); test_rv(rv, hContext, PANIC); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, mszReaders); test_rv(rv, hContext, PANIC); #else free(mszReaders); #endif printf("Testing SCardReleaseContext\t: "); rv = SCardReleaseContext(hContext); test_rv(rv, hContext, PANIC); printf("\n"); printf("PC/SC Test Completed Successfully !\n"); return 0; }
int CPCSCMngr::GetSCStatusString(CString* pSCStatus) { int status = STAT_OK; char *Readers=(char *)1, selected_reader[1000],msg[10000],msg_help[1000],convention[1000]; unsigned long len=SCARD_AUTOALLOCATE; DWORD protocol,state,a_len,r_len; unsigned char atr[40],TS,T0,TA1,TB1,TC1,TD1,FI,DI,TA2,TB2,TC2,TD2,TA3,TB3,TC3,TD3; int number_of_historical,pointer,ta1_sent=0,tb1_sent=0,tc1_sent=0,td1_sent=0,F,D; int transmission_protocol1,ta2_sent=0,tb2_sent=0,tc2_sent=0,td2_sent=0; int transmission_protocol2,ta3_sent=0,tb3_sent=0,tc3_sent=0,td3_sent=0; double work_etu,cycles; if (m_cardContext && m_hCard) { r_len=sizeof(selected_reader); a_len=sizeof(atr); status = TranslateSCardError(SCardStatus(m_hCard, selected_reader,&r_len,&state,&protocol,atr,&a_len)); } else status = STAT_SESSION_NOT_OPEN; if (status == STAT_OK) { sprintf_s(msg,10000,"Reader: %s\nState: %s\nProtocol: %s\nATR: %s\n\n",selected_reader,card_state(state),card_protocol(protocol),card_atr(atr,a_len)); TS=atr[0]; switch(TS){ case 59: strcpy_s(convention,1000,"Direct convention"); break; case 63: strcpy_s(convention,1000,"Inverse convention"); break; default: strcpy_s(convention,1000,"Unknown initial character"); } T0=atr[1]; number_of_historical=T0&0xF; ta1_sent=T0&16; tb1_sent=T0&32; tc1_sent=T0&64; td1_sent=T0&128; pointer=2; if(ta1_sent){ TA1=atr[pointer++]; DI=TA1&0xF; FI=TA1>>4; switch(FI){ case 0: F=372; break; case 1: F=372; break; case 2: F=558; break; case 3: F=744; break; case 4: F=1116; break; case 5: F=1488; break; case 6: F=1860; break; case 9: F=512; break; case 10: F=768; break; case 11: F=1024; break; case 12: F=1536; break; case 13: F=2048; break; default: F=0; } switch(DI){ case 1: D=1; break; case 2: D=2; break; case 3: D=4; break; case 4: D=8; break; case 5: D=16; break; case 6: D=32; break; case 8: D=12; break; case 9: D=20; break; default: D=0; } if(D==0||F==0) strcat_s(msg,10000,"Uncorrect frequency data in ATR\n"); work_etu=(double)(((double)F)/(double)((double)D*4000)); cycles=(double)(15/4)*(double)((((double)F)/(double)D)); } if(tb1_sent)TB1=atr[pointer++]; if(tc1_sent)TC1=atr[pointer++]; if(td1_sent){ TD1=atr[pointer++]; transmission_protocol1=TD1&0xF; ta2_sent=TD1&16; tb2_sent=TD1&32; tc2_sent=TD1&64; td2_sent=TD1&128; if(ta2_sent)TA2=atr[pointer++]; if(tb2_sent)TB2=atr[pointer++]; if(tc2_sent)TC2=atr[pointer++]; if(td2_sent) { TD2=atr[pointer++]; transmission_protocol2=TD2&0xF; ta3_sent=TD2&16; tb3_sent=TD2&32; tc3_sent=TD2&64; td3_sent=TD2&128; if(ta3_sent)TA3=atr[pointer++]; if(tb3_sent)TB3=atr[pointer++]; if(tc3_sent)TC3=atr[pointer++]; if(td3_sent){ TD3=atr[pointer++]; strcat_s(msg,10000,"Unusual ATR - not handling TD3 and further\n"); } } } sprintf_s(msg_help,1000,"Initial character: %s\n",convention); strcat_s(msg,10000,msg_help); if(!ta1_sent) sprintf_s(msg_help,1000,"TA1: not present\n"); else sprintf_s(msg_help,1000,"TA1: %02Xh (DI: %i, FI: %i -> D: %i, F: %i -> Work etu: %f ms, 15 Mhz cycles: %i)\n",(int)TA1,DI,FI,D,F,work_etu,(int)cycles); strcat_s(msg,10000,msg_help); if(!tb1_sent) sprintf_s(msg_help,1000,"TB1: not present\n"); else sprintf_s(msg_help,1000,"TB1: %02Xh (II: %i, PI1: %i [currently not used, should always be 0])\n",(int)TB1,(int)TB1>>5,(int)TB1&0x1F); strcat_s(msg,10000,msg_help); if(!tc1_sent) sprintf_s(msg_help,1000,"TC1: not present\n"); else if((int)TC1==255) sprintf_s(msg_help,1000,"TC1: %02Xh (special value: for T=0 guard time 2 etu, for T=1 guard time 1 etu)\n",(int)TC1); else sprintf_s(msg_help,1000,"TC1: %02Xh (extra guard time %i etu)\n",(int)TC1,(int)TC1); strcat_s(msg,10000,msg_help); if(td1_sent) { sprintf_s(msg_help,1000,"Protocol: %i\n",transmission_protocol1); strcat_s(msg,10000,msg_help); if(!ta2_sent) sprintf_s(msg_help,1000," TA2: not present\n"); else if(transmission_protocol1==1)sprintf_s(msg_help,1000," TA2: %02Xh (Protocol T=%i to be used, %s, %s)\n",(int)TA2,(int)TA2&0xF,TA2&0x80?"switching betweeen negotiable and specific modes not possible":"switching betweeen negotiable and specific modes possible",TA2&0x10?"transmission parameters implicitely defined":"transmission parameters explicitely defined"); else sprintf_s(msg_help,1000," TA2: %02Xh\n",(int)TA2); strcat_s(msg,10000,msg_help); if(!tb2_sent) sprintf_s(msg_help,1000," TB2: not present\n"); else sprintf_s(msg_help,1000," TB2: %02Xh\n",(int)TB2); strcat_s(msg,10000,msg_help); if(!tc2_sent) sprintf_s(msg_help,1000," TC2: not present\n"); else if(transmission_protocol1==0) sprintf_s(msg_help,1000," TC2: %02Xh (WI: %i -> work waiting time: %i work etu)\n",(int)TC2,(int)TC2,960*D*(int)TC2); else sprintf_s(msg_help,1000," TC2: %02Xh\n",(int)TC2); strcat_s(msg,10000,msg_help); } if(td2_sent) { sprintf_s(msg_help,1000,"Protocol: %i\n",transmission_protocol2); strcat_s(msg,10000,msg_help); if(!ta3_sent) sprintf_s(msg_help,1000," TA3: not present\n"); else if(transmission_protocol2==1) sprintf_s(msg_help,1000," TA3: %02Xh (IFSC: %i) \n",(int)TA3,(int)TA3); else sprintf_s(msg_help,1000," TA3: %02Xh\n",(int)TA3); strcat_s(msg,10000,msg_help); if(!tb3_sent) sprintf_s(msg_help,1000," TB3: not present\n"); else if(transmission_protocol2==1)sprintf_s(msg_help,1000," TB3: %02Xh (BWI: %i, CWI: %i -> BWT: %f s + 11 work etu , CWT: %i work etu)\n",(int)TB3,(int)TB3>>4,(int)TB3&0xF,(double)((1<<(TB3>>4))*960*372)/4000000,(1<<(TB3&0xF))+11); else sprintf_s(msg_help,1000," TB3: %02Xh\n",(int)TB3); strcat_s(msg,10000,msg_help); if(!tc3_sent) sprintf_s(msg_help,1000," TC3: not present\n"); else if(transmission_protocol2==1)sprintf_s(msg_help,1000," TC3: %02Xh (%s)\n",(int)TC3,TC3?"CRC used":"LRC used"); else sprintf_s(msg_help,1000," TC3: %02Xh\n",(int)TC3); strcat_s(msg,10000,msg_help); }
static uint32 handle_State(IRP* irp) { LONG rv; SCARDHANDLE hCard; DWORD state = 0, protocol = 0; DWORD readerLen; DWORD atrLen = MAX_ATR_SIZE; char * readerName; BYTE pbAtr[MAX_ATR_SIZE]; #ifdef WITH_DEBUG_SCARD int i; #endif stream_seek(irp->input, 0x24); stream_seek_uint32(irp->input); /* atrLen */ stream_seek(irp->input, 0x0c); stream_read_uint32(irp->input, hCard); stream_seek(irp->input, 0x04); #ifdef SCARD_AUTOALLOCATE readerLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #else readerLen = 256; readerName = xmalloc(readerLen); rv = SCardStatus(hCard, (LPSTR) readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #endif if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return sc_output_return(irp, rv); } DEBUG_SCARD("Success (hcard: 0x%08x len: %d state: 0x%08x, proto: 0x%08x)", (unsigned) hCard, (int) atrLen, (unsigned) state, (unsigned) protocol); #ifdef WITH_DEBUG_SCARD printf(" ATR: "); for (i = 0; i < atrLen; i++) printf("%02x%c", pbAtr[i], (i == atrLen - 1) ? ' ' : ':'); printf("\n"); #endif state = sc_map_state(state); stream_write_uint32(irp->output, state); stream_write_uint32(irp->output, protocol); stream_write_uint32(irp->output, atrLen); stream_write_uint32(irp->output, 0x00000001); stream_write_uint32(irp->output, atrLen); stream_write(irp->output, pbAtr, atrLen); sc_output_repos(irp, atrLen); sc_output_alignment(irp, 8); #ifdef SCARD_AUTOALLOCATE xfree(readerName); #else xfree(readerName); #endif return rv; }
/** * checkForNewPCSCToken looks into a specific slot for a token. * * @param slot Pointer to slot structure. * * @return * <P><TABLE> * <TR><TD>Code</TD><TD>Meaning</TD></TR> * <TR> * <TD>CKR_OK </TD> * <TD>Success </TD> * </TR> * <TR> * <TD>CKR_HOST_MEMORY </TD> * <TD>Error getting memory (malloc) </TD> * </TR> * <TR> * <TD>CKR_GENERAL_ERROR </TD> * <TD>Error opening slot directory </TD> * </TR> * </TABLE></P> */ static int checkForNewPCSCToken(struct p11Slot_t *slot) { struct p11Token_t *ptoken; int rc, i; LONG rv; DWORD dwActiveProtocol; WORD feature; DWORD featurecode, lenr, atrlen,readernamelen,state,protocol; unsigned char buf[256]; unsigned char atr[36]; char *po; FUNC_CALLED(); if (slot->closed) { FUNC_RETURNS(CKR_TOKEN_NOT_PRESENT); } rv = SCardConnect(slot->context, slot->readername, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &(slot->card), &dwActiveProtocol); #ifdef DEBUG debug("SCardConnect (%i, %s): %s\n", slot->id, slot->readername, pcsc_error_to_string(rv)); #endif if (rv == SCARD_E_NO_SMARTCARD || rv == SCARD_W_REMOVED_CARD || rv == SCARD_E_SHARING_VIOLATION) { FUNC_RETURNS(CKR_TOKEN_NOT_PRESENT); } if (rv != SCARD_S_SUCCESS) { closeSlot(slot); FUNC_FAILS(CKR_DEVICE_ERROR, pcsc_error_to_string(rv)); } if (!slot->hasFeatureVerifyPINDirect) { rv = SCardControl(slot->card, SCARD_CTL_CODE(3400), NULL,0, buf, sizeof(buf), &lenr); #ifdef DEBUG debug("SCardControl (CM_IOCTL_GET_FEATURE_REQUEST): %s\n", pcsc_error_to_string(rv)); #endif /* Ignore the feature codes if an error occured */ if (rv == SCARD_S_SUCCESS) { for (i = 0; i < lenr; i += 6) { feature = buf[i]; featurecode = (buf[i + 2] << 24) + (buf[i + 3] << 16) + (buf[i + 4] << 8) + buf[i + 5]; #ifdef DEBUG debug("%s - 0x%08X\n", pcsc_feature_to_string(feature), featurecode); #endif if (feature == FEATURE_VERIFY_PIN_DIRECT) { po = getenv("PKCS11_IGNORE_PINPAD"); #ifdef DEBUG if (po) { debug("PKCS11_IGNORE_PINPAD=%s\n", po); } else { debug("PKCS11_IGNORE_PINPAD not found\n"); } #endif if (!po || (*po == '0')) { #ifdef DEBUG debug("Slot supports feature VERIFY_PIN_DIRECT - setting CKF_PROTECTED_AUTHENTICATION_PATH for token\n"); #endif slot->hasFeatureVerifyPINDirect = featurecode; } } } } } readernamelen = 0; atrlen = sizeof(atr); rc = SCardStatus(slot->card, NULL, &readernamelen, &state, &protocol, atr, &atrlen); if (rc != SCARD_S_SUCCESS) { closeSlot(slot); FUNC_FAILS(CKR_DEVICE_ERROR, pcsc_error_to_string(rc)); } rc = newToken(slot, atr, atrlen, &ptoken); if (rc != CKR_OK) { FUNC_FAILS(rc, "newToken() failed"); } FUNC_RETURNS(rc); }
PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ResetCard( HANDLE devNo, unsigned char *srATR, short *srATRLen, short ivCardSeat) { // DWORD ActiveProtocol; DWORD dwCardState=0; BYTE AtrBuffer[32]; DWORD AtrLen ; // LPTSTR cardname; char cardname[256]; DWORD dw = 0; BYTE buf[32]; // ret = SCardStatus((SCARDHANDLE)devNo, NULL, NULL, &dwCardState, &ActiveProtocol, NULL, &AtrLen); ret = SCardStatus((SCARDHANDLE)devNo, cardname, &dw, &dwCardState, &ActiveProtocol, buf, &AtrLen); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardStatus; } switch ( dwCardState ) { case SCARD_ABSENT: // printf("Card absent.\n"); return CER_NOCARD; case SCARD_SWALLOWED: // printf("Card swallowed.\n"); // //The SCardReconnect function reestablishes an existing connection between //the calling application and a smart card. //This function moves a card handle from direct access to general access, //or acknowledges and clears an error condition that is preventing further //access to the card. // //SCARD_LEAVE_CARD Don't do anything special on reconnect. //SCARD_RESET_CARD Reset the card (Warm Reset). //SCARD_UNPOWER_CARD Power down the card and reset it (Cold Reset). ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , ActiveProtocol , SCARD_UNPOWER_CARD , &ActiveProtocol); if (ret != SCARD_S_SUCCESS) { GetErrorCode(ret); return CER_PCSC_SCardReconnect; } break; case SCARD_PRESENT: // printf("Card present.\n"); case SCARD_NEGOTIABLE: // printf("Card reset and waiting PTS negotiation.\n"); case SCARD_SPECIFIC: // printf("Card has specific communication protocols set.\n"); // //The SCardReconnect function reestablishes an existing connection between //the calling application and a smart card. //This function moves a card handle from direct access to general access, //or acknowledges and clears an error condition that is preventing further //access to the card. // //SCARD_LEAVE_CARD Don't do anything special on reconnect. //SCARD_RESET_CARD Reset the card (Warm Reset). //SCARD_UNPOWER_CARD Power down the card and reset it (Cold Reset). ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , ActiveProtocol, SCARD_RESET_CARD , &ActiveProtocol); if (ret != SCARD_S_SUCCESS) { //GetErrorCode(ret); return CER_PCSC_SCardReconnect; } break; case SCARD_POWERED: // printf("Card has power.\n"); // //The SCardReconnect function reestablishes an existing connection between //the calling application and a smart card. //This function moves a card handle from direct access to general access, //or acknowledges and clears an error condition that is preventing further //access to the card. // //SCARD_LEAVE_CARD Don't do anything special on reconnect. //SCARD_RESET_CARD Reset the card (Warm Reset). //SCARD_UNPOWER_CARD Power down the card and reset it (Cold Reset). /* ret = SCardReconnect((SCARDHANDLE)devNo,SCARD_SHARE_SHARED , SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 , SCARD_RESET_CARD , &ActiveProtocol); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardReconnect; } */ break; default: // printf("Unknown or unexpected card state.\n"); return CER_UNKNOWN; } AtrLen = 0x20; //Microsoft Define Atrlen<=0x20; ret = SCardStatus((SCARDHANDLE)devNo, NULL, NULL, &dwCardState, &ActiveProtocol, (LPBYTE)&AtrBuffer, &AtrLen); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardStatus; } *srATRLen = (short)AtrLen; memcpy(srATR, AtrBuffer, AtrLen); /*if ((memcmp(srATR+4,"\x00\x81",2)!=0)&&(memcmp(srATR+5,"\x00\x81",2)!=0)&&(memcmp(srATR+7,"\x00\x81",2)!=0)&&(memcmp(srATR+4,"\x86\x01",2)!=0)&&(memcmp(srATR+5,"\x86\x01",2)!=0)&&(memcmp(srATR+7,"\x86\x01",2)!=0)) { return CER_NOCARD; } */ return EXCUTE_SUC ; }
PCSCREADERDRIVERDLL_API unsigned short CCONV HD_GetDescriptor( HANDLE devNo, char *descriptor ) { // unsigned char tmpstr[100] ; // unsigned long pcbAttrLen; // unsigned short i; // //The SCardGetAttrib function gets the current reader attributes for the given handle. //It does not affect the state of the reader, driver, or card. // // DWORD ActiveProtocol; DWORD dwCardState=0; BYTE AtrBuffer[32]; DWORD AtrLen ; short i; char tmpstr[100]; ret = SCardStatus((SCARDHANDLE)devNo, NULL, NULL, &dwCardState, &ActiveProtocol, NULL, &AtrLen); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardStatus; } /* ret = SCardGetAttrib((SCARDHANDLE)devNo, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardGetAttrib; } ret = SCardGetAttrib((SCARDHANDLE)devNo, SCARD_ATTR_DEVICE_FRIENDLY_NAME, tmpstr, &pcbAttrLen); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardGetAttrib; } */ AtrLen = 0x20; //Microsoft Define Atrlen<=0x20; ret = SCardStatus((SCARDHANDLE)devNo, NULL, NULL, &dwCardState, &ActiveProtocol, (LPBYTE)&AtrBuffer, &AtrLen); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardStatus; } descriptor[0] = '\0' ; tmpstr[0] = '\0'; for( i=0 ; i < (short)AtrLen ; i++) byte2str_chen(tmpstr,AtrBuffer[i]) ; HD_RightChar(tmpstr,26,descriptor); descriptor[26] = '\0' ; // SCardFreeMemory((SCARDCONTEXT)ContextNo,&pcbAttrLen); return EXCUTE_SUC ; }
LC_CLIENT_RESULT LC_Client_ConnectCard(LC_CLIENT *cl, const char *rname, LC_CARD **pCard) { LC_CLIENT_RESULT res; LONG rv; SCARDHANDLE scardHandle; DWORD dwActiveProtocol; LC_CARD *card; char readerName[256]; DWORD pcchReaderLen; BYTE pbAtr[MAX_ATR_SIZE]; DWORD dwAtrLen; DWORD dwState; GWEN_BUFFER *bDriverType; GWEN_BUFFER *bReaderType; uint32_t rflags=0; assert(cl); DBG_INFO(LC_LOGDOMAIN, "Trying protocol T1"); rv=SCardConnect(cl->scardContext, rname, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T1, &scardHandle, &dwActiveProtocol); if (rv!=SCARD_S_SUCCESS) { DBG_INFO(LC_LOGDOMAIN, "Trying protocol T0"); rv=SCardConnect(cl->scardContext, rname, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0, &scardHandle, &dwActiveProtocol); } #ifdef SCARD_PROTOCOL_RAW if (rv!=SCARD_S_SUCCESS) { DBG_INFO(LC_LOGDOMAIN, "Trying protocol RAW"); rv=SCardConnect(cl->scardContext, rname, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_RAW, &scardHandle, &dwActiveProtocol); } #endif if (rv!=SCARD_S_SUCCESS) { DBG_INFO(LC_LOGDOMAIN, "SCardConnect: %04lx", (long unsigned int) rv); return LC_Client_ResultIoError; } /* get protocol and ATR */ DBG_INFO(LC_LOGDOMAIN, "Reading protocol and ATR"); pcchReaderLen=sizeof(readerName); dwAtrLen=sizeof(pbAtr); rv=SCardStatus(scardHandle, readerName, &pcchReaderLen, &dwState, &dwActiveProtocol, pbAtr, &dwAtrLen); if (rv!=SCARD_S_SUCCESS) { DBG_ERROR(LC_LOGDOMAIN, "SCardStatus: %04lx", (long unsigned int) rv); SCardDisconnect(scardHandle, SCARD_UNPOWER_CARD); return LC_Client_ResultIoError; } /* derive reader and driver type from name */ DBG_INFO(LC_LOGDOMAIN, "Getting reader- and driver type"); bDriverType=GWEN_Buffer_new(0, 32, 0, 1); bReaderType=GWEN_Buffer_new(0, 32, 0, 1); res=LC_Client_GetReaderAndDriverType(cl, readerName, bDriverType, bReaderType, &rflags); if (res) { DBG_INFO(LC_LOGDOMAIN, "Unable to determine type of reader [%s] (%d), assuming generic pcsc", readerName, res); GWEN_Buffer_AppendString(bDriverType, "generic_pcsc"); GWEN_Buffer_AppendString(bReaderType, "generic_pcsc"); } /* create new card */ card=LC_Card_new(cl, scardHandle, readerName, dwActiveProtocol, "processor", /* cardType */ rflags, dwAtrLen?pbAtr:0, /* atrBuf */ dwAtrLen); /* atrLen */ /* complete card data */ LC_Card_SetDriverType(card, GWEN_Buffer_GetStart(bDriverType)); LC_Card_SetReaderType(card, GWEN_Buffer_GetStart(bReaderType)); GWEN_Buffer_free(bReaderType); GWEN_Buffer_free(bDriverType); *pCard=card; return LC_Client_ResultOk; }
// // FUNCTION NAME: SIM_Status // // DESCRIPTION: this is a wrapper for pcsclite SCardStatus function. // Its job is to call that function and manage error messages // eventually returned. // // INPUT PARAMETERS: // SCARDHANDLE hCard connection handler for this card. // // OUTPUT PARAMETERS: RESPONSE* // If nothing goes wrong, atr from the card is returned. // RESPONSE* SIM_Status(SCARDHANDLE hCard) { LONG rv; DWORD pcchReaderLen, dwState, dwProtocol; BYTE pbAtr[MAX_ATR_SIZE]; DWORD pcbAtrLen; int const buf_size = 1024; LPSTR lettori = (LPSTR)malloc(sizeof(char) * buf_size); pcchReaderLen = buf_size; rv = SCardStatus(hCard, lettori, &pcchReaderLen, &dwState, &dwProtocol, pbAtr, &pcbAtrLen); switch(rv) { case SCARD_E_READER_UNAVAILABLE: { bail(EXIT_FAILURE, "SIM_Status:", ERR_READER_REMOVED); } case SCARD_E_INSUFFICIENT_BUFFER: { bail(EXIT_FAILURE, "SIM_Status:",ERR_INSUFFICIENT_BUFFER); } case SCARD_E_INVALID_HANDLE: { bail(EXIT_FAILURE, "SIM_Status:",ERR_INVALID_CONTEXT_HANDLER); } case SCARD_S_SUCCESS: { printf("\n\nCARD STATUS = :\n"); switch(dwState) { case SCARD_ABSENT: { printf("\tThere is no card into the reader."); break; } case SCARD_PRESENT: { printf("\tCard present but not ready to be used."); break; } case SCARD_SWALLOWED: { printf("\tCard present and ready to be used, but not powered."); break; } case SCARD_POWERED: { printf("\tCard powered, but mode not recognized by the driver."); break; } case SCARD_NEGOTIABLE: { printf("\tCard reset and waiting PTS negotiation."); break; } case SCARD_SPECIFIC: { printf("\tCard reset and specific communication protocols established."); break; } default: { printf("\tCARD ANSWERED WITH AN UNKNOWN STATE: %.2X.",dwState); } } printf("\n\nCommunication protocol is:\n"); switch(dwProtocol) { case SCARD_PROTOCOL_T0: { printf("\tT=0.\n"); break; } case SCARD_PROTOCOL_T1: { printf("\tT=1.\n"); break; } default: { printf("\tCARD ANSWERED WITH AN UNKNOWN PROTOCOL.\n"); } } printf("\n\nATR = "); print_array(pbAtr,pcbAtrLen); printf("\n\nATR length = %i.\n",pcbAtrLen); RESPONSE* resp = create_b_list(); int i; for(i=0; i<pcbAtrLen; i++) { blist_add_element(resp,pbAtr[i]); } return(resp); } default: { int errno_saved = errno; printf("\nValue returned = %.2X\n",rv); bail_with_errno(EXIT_FAILURE, errno_saved, "SIM_Status:",ERR_WRONG_RETURN_VALUE); } } }
static LONG MSGRemoveContext(SCARDCONTEXT hContext, SCONTEXT * threadContext) { LONG rv; int lrv; if (threadContext->hContext != hContext) return SCARD_E_INVALID_VALUE; (void)pthread_mutex_lock(&threadContext->cardsList_lock); while (list_size(&threadContext->cardsList) != 0) { READER_CONTEXT * rContext = NULL; SCARDHANDLE hCard, hLockId; void *ptr; /* * Disconnect each of these just in case */ ptr = list_get_at(&threadContext->cardsList, 0); if (NULL == ptr) { Log1(PCSC_LOG_CRITICAL, "list_get_at failed"); continue; } hCard = *(int32_t *)ptr; /* * Unlock the sharing */ rv = RFReaderInfoById(hCard, &rContext); if (rv != SCARD_S_SUCCESS) { (void)pthread_mutex_unlock(&threadContext->cardsList_lock); return rv; } hLockId = rContext->hLockId; rContext->hLockId = 0; if (hCard != hLockId) { /* * if the card is locked by someone else we do not reset it * and simulate a card removal */ rv = SCARD_W_REMOVED_CARD; } else { /* * We will use SCardStatus to see if the card has been * reset there is no need to reset each time * Disconnect is called */ rv = SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL); } if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD) (void)SCardDisconnect(hCard, SCARD_LEAVE_CARD); else (void)SCardDisconnect(hCard, SCARD_RESET_CARD); /* Remove entry from the list */ lrv = list_delete_at(&threadContext->cardsList, 0); if (lrv < 0) Log2(PCSC_LOG_CRITICAL, "list_delete_at failed with return value: %d", lrv); UNREF_READER(rContext) } (void)pthread_mutex_unlock(&threadContext->cardsList_lock); list_destroy(&threadContext->cardsList); /* We only mark the context as no longer in use. * The memory is freed in MSGCleanupCLient() */ threadContext->hContext = 0; return SCARD_S_SUCCESS; }
static DWORD handle_Status(IRP *irp, tbool wide) { LONG rv; SCARDHANDLE hCard; DWORD state, protocol; DWORD readerLen = 0; DWORD atrLen = 0; char * readerName; BYTE pbAtr[MAX_ATR_SIZE]; uint32 dataLength; int pos, poslen1, poslen2; #ifdef WITH_DEBUG_SCARD int i; #endif stream_seek(irp->input, 0x24); stream_read_uint32(irp->input, readerLen); stream_read_uint32(irp->input, atrLen); stream_seek(irp->input, 0x0c); stream_read_uint32(irp->input, hCard); stream_seek(irp->input, 0x4); atrLen = MAX_ATR_SIZE; #ifdef SCARD_AUTOALLOCATE readerLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #else readerLen = 256; readerName = xmalloc(readerLen); rv = SCardStatus(hCard, (LPSTR) readerName, &readerLen, &state, &protocol, pbAtr, &atrLen); #endif if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return sc_output_return(irp, rv); } DEBUG_SCARD("Success (state: 0x%08x, proto: 0x%08x)", (unsigned) state, (unsigned) protocol); DEBUG_SCARD(" Reader: \"%s\"", readerName ? readerName : "NULL"); #ifdef WITH_DEBUG_SCARD printf(" ATR: "); for (i = 0; i < atrLen; i++) printf("%02x%c", pbAtr[i], (i == atrLen - 1) ? ' ' : ':'); printf("\n"); #endif state = sc_map_state(state); poslen1 = stream_get_pos(irp->output); stream_write_uint32(irp->output, readerLen); stream_write_uint32(irp->output, 0x00020000); stream_write_uint32(irp->output, state); stream_write_uint32(irp->output, protocol); stream_write(irp->output, pbAtr, atrLen); if (atrLen < 32) stream_write_zero(irp->output, 32 - atrLen); stream_write_uint32(irp->output, atrLen); poslen2 = stream_get_pos(irp->output); stream_write_uint32(irp->output, readerLen); dataLength = sc_output_string(irp, readerName, wide); dataLength += sc_output_string(irp, "\0", wide); sc_output_repos(irp, dataLength); pos = stream_get_pos(irp->output); stream_set_pos(irp->output, poslen1); stream_write_uint32(irp->output,dataLength); stream_set_pos(irp->output, poslen2); stream_write_uint32(irp->output,dataLength); stream_set_pos(irp->output, pos); sc_output_alignment(irp, 8); #ifdef SCARD_AUTOALLOCATE /* SCardFreeMemory(NULL, readerName); */ free(readerName); #else xfree(readerName); #endif return rv; }
/************************ READER CHECK ***************************/ LONG acr122UReaderCheck( tReader *pReader, BOOL *pReaderSupported ) { static char pbReader[MAX_READERNAME] = ""; DWORD dwAtrLen, dwReaderLen, dwState, dwProt; DWORD dwRecvLength; BYTE pbAtr[MAX_ATR_SIZE] = ""; int i; LONG rv; BYTE pbRecvBuffer[MAX_FIRMWARE_STRING_LENGTH]; *pReaderSupported = FALSE; /* First check the name reported by pcscd to see if it's possible supported */ for (i = 0; (i < SUPPORTED_READER_NAME_ARRAY_COUNT) & (*pReaderSupported == FALSE) ; i++) { if ( strncmp( pReader->name, SUPPORTED_READER_NAME_ARRAY[i], sizeof(SUPPORTED_READER_NAME_ARRAY[i])-1) == 0 ) *pReaderSupported = TRUE; } /* If even the name is not supported, then we're done */ if ( *pReaderSupported == FALSE ) return (SCARD_S_SUCCESS ); /* just because the name was OK, doesn't mean it'll actually work! */ *pReaderSupported = FALSE; /* Get firmware version and check it's really a ACR122* */ dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_GET_READER_FIRMWARE, sizeof(APDU_GET_READER_FIRMWARE), pbRecvBuffer, &dwRecvLength); if (rv != SCARD_S_SUCCESS) return (rv); /* Search the list of supported firmware versions (reader versions) */ /* to check we are compatible with it - or have tested with it */ /* NULL terminate the BYTE array for subsequent string compares */ pbRecvBuffer[dwRecvLength] = '\0'; for (i = 0; (i < SUPPORTED_READER_FIRMWARE_ARRAY_COUNT) & (*pReaderSupported == FALSE) ; i++) { if ( strncmp( ((char *)pbRecvBuffer), SUPPORTED_READER_FIRMWARE_ARRAY[i], sizeof(SUPPORTED_READER_FIRMWARE_ARRAY[i])-1) == 0 ) *pReaderSupported = TRUE; } /* if we didn't find that we support it, then we're done */ if ( *pReaderSupported == FALSE ) return( SCARD_S_SUCCESS ); /* no actual communication errors to report */ /* If we got this far then the general name and specific firmware version is supported */ /* Get ATR so we can tell if there is a SAM in the reader */ dwAtrLen = sizeof(pbAtr); dwReaderLen = sizeof(pbReader); SCardStatus( (SCARDHANDLE) (pReader->hCard), pbReader, &dwReaderLen, &dwState, &dwProt, pbAtr, &dwAtrLen); dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_SET_RETRY, sizeof(APDU_SET_RETRY), pbRecvBuffer, &dwRecvLength); if (rv != SCARD_S_SUCCESS) return (rv); /* get card status ATR first two bytes = ACS_NO_SAM= '3B00' */ if ( (pbAtr[SW1] != 0x3B) || (pbAtr[SW2] != 0x00) ) { dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_GET_SAM_SERIAL, sizeof(APDU_GET_SAM_SERIAL), pbRecvBuffer, &dwRecvLength); if (rv == SCARD_S_SUCCESS) { sPrintBufferHex(pReader->SAM_serial, dwRecvLength, pbRecvBuffer); #if 0 sprintf(messageString, "SAM Serial: %s", pReader->SAM_serial); readersLogMessage(LOG_INFO, 1, messageString); #endif } else return (rv); dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_GET_SAM_ID, sizeof(APDU_GET_SAM_ID), pbRecvBuffer, &dwRecvLength); if (rv == SCARD_S_SUCCESS) { sPrintBufferHex(pReader->SAM_id, dwRecvLength, pbRecvBuffer); #if 0 sprintf(messageString, "SAM ID: %s", pReader->SAM_id); readersLogMessage(LOG_INFO, 1, messageString); #endif } else return( rv ); pReader->SAM = TRUE; } /* Turning RATS off thus a JCOP tag will be detected as emulating a DESFIRE */ apduSend(pReader->hCard, APDU_RATS_14443_4_OFF, sizeof(APDU_RATS_14443_4_OFF), pbRecvBuffer, &dwRecvLength); return( SCARD_S_SUCCESS ); }
int main(int argc, char *argv[]) { LONG rv; SCARDCONTEXT hContext; DWORD dwReaders; LPSTR mszReaders = NULL; char *ptr, **readers = NULL; int nbReaders; SCARDHANDLE hCard; DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen; BYTE pbAtr[MAX_ATR_SIZE] = ""; char pbReader[MAX_READERNAME] = ""; int reader_nb; unsigned int i; unsigned char bSendBuffer[MAX_BUFFER_SIZE]; unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; DWORD send_length, length; DWORD verify_ioctl = 0; DWORD modify_ioctl = 0; DWORD pin_properties_ioctl = 0; DWORD mct_readerdirect_ioctl = 0; DWORD properties_in_tlv_ioctl = 0; DWORD ccid_esc_command = 0; SCARD_IO_REQUEST pioRecvPci; SCARD_IO_REQUEST pioSendPci; PCSC_TLV_STRUCTURE *pcsc_tlv; #if defined(VERIFY_PIN) | defined(MODIFY_PIN) int offset; #endif #ifdef VERIFY_PIN PIN_VERIFY_STRUCTURE *pin_verify; #endif #ifdef MODIFY_PIN PIN_MODIFY_STRUCTURE *pin_modify; #endif printf("SCardControl sample code\n"); printf("V 1.4 © 2004-2010, Ludovic Rousseau <*****@*****.**>\n\n"); printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL!\n"); printf("Do NOT use it unless you really know what you do.\n\n" NORMAL); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (rv != SCARD_S_SUCCESS) { printf("SCardEstablishContext: Cannot Connect to Resource Manager %ulX\n", rv); return 1; } /* Retrieve the available readers list */ rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); PCSC_ERROR_EXIT(rv, "SCardListReaders") mszReaders = malloc(sizeof(char)*dwReaders); if (mszReaders == NULL) { printf("malloc: not enough memory\n"); goto end; } rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); if (rv != SCARD_S_SUCCESS) printf("SCardListReader: %ulX\n", rv); /* Extract readers from the null separated string and get the total * number of readers */ nbReaders = 0; ptr = mszReaders; while (*ptr != '\0') { ptr += strlen(ptr)+1; nbReaders++; } if (nbReaders == 0) { printf("No reader found\n"); goto end; } /* allocate the readers table */ readers = calloc(nbReaders, sizeof(char *)); if (NULL == readers) { printf("Not enough memory for readers[]\n"); goto end; } /* fill the readers table */ nbReaders = 0; ptr = mszReaders; printf("Available readers (use command line argument to select)\n"); while (*ptr != '\0') { printf("%d: %s\n", nbReaders, ptr); readers[nbReaders] = ptr; ptr += strlen(ptr)+1; nbReaders++; } printf("\n"); if (argc > 1) { reader_nb = atoi(argv[1]); if (reader_nb < 0 || reader_nb >= nbReaders) { printf("Wrong reader index: %d\n", reader_nb); goto end; } } else reader_nb = 0; /* connect to a reader (even without a card) */ dwActiveProtocol = -1; printf("Using reader: " GREEN "%s\n" NORMAL, readers[reader_nb]); rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); printf(" Protocol: " GREEN "%uld\n" NORMAL, dwActiveProtocol); PCSC_ERROR_EXIT(rv, "SCardConnect") #ifdef GET_GEMPC_FIRMWARE /* get GemPC firmware */ printf(" Get GemPC Firmware\n"); /* this is specific to Gemalto readers */ bSendBuffer[0] = 0x02; rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer, 1, bRecvBuffer, sizeof(bRecvBuffer), &length); printf(" Firmware: " GREEN); for (i=0; i<length; i++) printf("%02X ", bRecvBuffer[i]); printf(NORMAL "\n"); bRecvBuffer[length] = '\0'; printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length); PCSC_ERROR_CONT(rv, "SCardControl") #endif /* does the reader support PIN verification? */ rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, bRecvBuffer, sizeof(bRecvBuffer), &length); PCSC_ERROR_EXIT(rv, "SCardControl") printf(" TLV (%uld): " GREEN, length); for (i=0; i<length; i++) printf("%02X ", bRecvBuffer[i]); printf(NORMAL "\n"); PCSC_ERROR_CONT(rv, "SCardControl(CM_IOCTL_GET_FEATURE_REQUEST)") if (length % sizeof(PCSC_TLV_STRUCTURE)) { printf("Inconsistent result! Bad TLV values!\n"); goto end; } /* get the number of elements instead of the complete size */ length /= sizeof(PCSC_TLV_STRUCTURE); pcsc_tlv = (PCSC_TLV_STRUCTURE *)bRecvBuffer; for (i = 0; i < length; i++) { switch (pcsc_tlv[i].tag) { case FEATURE_VERIFY_PIN_DIRECT: PRINT_GREEN("Reader supports", "FEATURE_VERIFY_PIN_DIRECT"); verify_ioctl = ntohl(pcsc_tlv[i].value); break; case FEATURE_MODIFY_PIN_DIRECT: PRINT_GREEN("Reader supports", "FEATURE_MODIFY_PIN_DIRECT"); modify_ioctl = ntohl(pcsc_tlv[i].value); break; case FEATURE_IFD_PIN_PROPERTIES: PRINT_GREEN("Reader supports", "FEATURE_IFD_PIN_PROPERTIES"); pin_properties_ioctl = ntohl(pcsc_tlv[i].value); break; case FEATURE_MCT_READER_DIRECT: PRINT_GREEN("Reader supports", "FEATURE_MCT_READER_DIRECT"); mct_readerdirect_ioctl = ntohl(pcsc_tlv[i].value); break; case FEATURE_GET_TLV_PROPERTIES: PRINT_GREEN("Reader supports", "FEATURE_GET_TLV_PROPERTIES"); properties_in_tlv_ioctl = ntohl(pcsc_tlv[i].value); break; case FEATURE_CCID_ESC_COMMAND: PRINT_GREEN("Reader supports", "FEATURE_CCID_ESC_COMMAND"); ccid_esc_command = ntohl(pcsc_tlv[i].value); break; default: PRINT_RED_DEC("Can't parse tag", pcsc_tlv[i].tag); } } printf("\n"); if (properties_in_tlv_ioctl) { int value; int ret; rv = SCardControl(hCard, properties_in_tlv_ioctl, NULL, 0, bRecvBuffer, sizeof(bRecvBuffer), &length); PCSC_ERROR_CONT(rv, "SCardControl(GET_TLV_PROPERTIES)") printf("GET_TLV_PROPERTIES (" GREEN "%uld" NORMAL "): " GREEN, length); for (i=0; i<length; i++) printf("%02X ", bRecvBuffer[i]); printf(NORMAL "\n"); printf("\nDisplay all the properties:\n"); parse_properties(bRecvBuffer, length); printf("\nFind a specific property:\n"); ret = PCSCv2Part10_find_TLV_property_by_tag_from_buffer(bRecvBuffer, length, PCSCv2_PART10_PROPERTY_wIdVendor, &value); if (ret) PRINT_RED_DEC(" wIdVendor", ret); else PRINT_GREEN_HEX4(" wIdVendor", value); ret = PCSCv2Part10_find_TLV_property_by_tag_from_hcard(hCard, PCSCv2_PART10_PROPERTY_wIdProduct, &value); if (ret) PRINT_RED_DEC(" wIdProduct", ret); else PRINT_GREEN_HEX4(" wIdProduct", value); printf("\n"); } if (mct_readerdirect_ioctl) { char secoder_info[] = { 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; rv = SCardControl(hCard, mct_readerdirect_ioctl, secoder_info, sizeof(secoder_info), bRecvBuffer, sizeof(bRecvBuffer), &length); PCSC_ERROR_CONT(rv, "SCardControl(MCT_READER_DIRECT)") printf("MCT_READER_DIRECT (%uld): ", length); for (i=0; i<length; i++) printf("%02X ", bRecvBuffer[i]); printf("\n"); } if (pin_properties_ioctl) { PIN_PROPERTIES_STRUCTURE *pin_properties; rv = SCardControl(hCard, pin_properties_ioctl, NULL, 0, bRecvBuffer, sizeof(bRecvBuffer), &length); PCSC_ERROR_CONT(rv, "SCardControl(pin_properties_ioctl)") printf("PIN PROPERTIES (" GREEN "%uld" NORMAL "): " GREEN, length); for (i=0; i<length; i++) printf("%02X ", bRecvBuffer[i]); printf(NORMAL "\n"); pin_properties = (PIN_PROPERTIES_STRUCTURE *)bRecvBuffer; PRINT_GREEN_HEX4(" wLcdLayout", pin_properties -> wLcdLayout); PRINT_GREEN_DEC(" bEntryValidationCondition", pin_properties -> bEntryValidationCondition); PRINT_GREEN_DEC(" bTimeOut2", pin_properties -> bTimeOut2); printf("\n"); } #ifdef GET_GEMPC_FIRMWARE if (ccid_esc_command) { /* get GemPC firmware */ printf("Get GemPC Firmware\n"); /* this is specific to Gemalto readers */ bSendBuffer[0] = 0x02; rv = SCardControl(hCard, ccid_esc_command, bSendBuffer, 1, bRecvBuffer, sizeof(bRecvBuffer), &length); printf(" Firmware: " GREEN); for (i=0; i<length; i++) printf("%02X ", bRecvBuffer[i]); printf(NORMAL "\n"); bRecvBuffer[length] = '\0'; printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length); PCSC_ERROR_CONT(rv, "SCardControl") } #endif if (0 == verify_ioctl) { printf("Reader %s does not support PIN verification\n", readers[reader_nb]); goto end; } /* get card status */ dwAtrLen = sizeof(pbAtr); dwReaderLen = sizeof(pbReader); rv = SCardStatus(hCard, pbReader, &dwReaderLen, &dwState, &dwProt, pbAtr, &dwAtrLen); printf(" Reader: %s (length %uld bytes)\n", pbReader, dwReaderLen); printf(" State: 0x%04ulX\n", dwState); printf(" Prot: %uld\n", dwProt); printf(" ATR (length %uld bytes):", dwAtrLen); for (i=0; i<dwAtrLen; i++) printf(" %02X", pbAtr[i]); printf("\n"); PCSC_ERROR_CONT(rv, "SCardStatus") if (dwState & SCARD_ABSENT) { printf("No card inserted\n"); goto end; } /* connect to a reader (even without a card) */ dwActiveProtocol = -1; rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, &dwActiveProtocol); printf(" Protocol: %uld\n", dwActiveProtocol); PCSC_ERROR_EXIT(rv, "SCardReconnect") switch(dwActiveProtocol) { case SCARD_PROTOCOL_T0: pioSendPci = *SCARD_PCI_T0; break; case SCARD_PROTOCOL_T1: pioSendPci = *SCARD_PCI_T1; break; default: printf("Unknown protocol. No card present?\n"); return -1; } /* APDU select applet */ printf("Select applet: "); send_length = 11; memcpy(bSendBuffer, "\x00\xA4\x04\x00\x06\xA0\x00\x00\x00\x18\xFF", send_length); for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); printf(" card response:"); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n"); PCSC_ERROR_EXIT(rv, "SCardTransmit") if ((bRecvBuffer[0] != 0x90) || (bRecvBuffer[1] != 0x00)) { printf("Error: test applet not found!\n"); goto end; } #ifdef VERIFY_PIN /* verify PIN */ printf(" Secure verify PIN\n"); pin_verify = (PIN_VERIFY_STRUCTURE *)bSendBuffer; /* table for bEntryValidationCondition * 0x01: Max size reached * 0x02: Validation key pressed * 0x04: Timeout occured */ /* PC/SC v2.02.05 Part 10 PIN verification data structure */ pin_verify -> bTimerOut = 0x00; pin_verify -> bTimerOut2 = 0x00; pin_verify -> bmFormatString = 0x82; pin_verify -> bmPINBlockString = 0x04; pin_verify -> bmPINLengthFormat = 0x00; pin_verify -> wPINMaxExtraDigit = 0x0408; /* Min Max */ pin_verify -> bEntryValidationCondition = 0x02; /* validation key pressed */ pin_verify -> bNumberMessage = 0x01; pin_verify -> wLangId = 0x0904; pin_verify -> bMsgIndex = 0x00; pin_verify -> bTeoPrologue[0] = 0x00; pin_verify -> bTeoPrologue[1] = 0x00; pin_verify -> bTeoPrologue[2] = 0x00; /* pin_verify -> ulDataLength = 0x00; we don't know the size yet */ /* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */ offset = 0; pin_verify -> abData[offset++] = 0x00; /* CLA */ pin_verify -> abData[offset++] = 0x20; /* INS: VERIFY */ pin_verify -> abData[offset++] = 0x00; /* P1 */ pin_verify -> abData[offset++] = 0x00; /* P2 */ pin_verify -> abData[offset++] = 0x08; /* Lc: 8 data bytes */ pin_verify -> abData[offset++] = 0x30; /* '0' */ pin_verify -> abData[offset++] = 0x30; /* '0' */ pin_verify -> abData[offset++] = 0x30; /* '0' */ pin_verify -> abData[offset++] = 0x30; /* '0' */ pin_verify -> abData[offset++] = 0x00; /* '\0' */ pin_verify -> abData[offset++] = 0x00; /* '\0' */ pin_verify -> abData[offset++] = 0x00; /* '\0' */ pin_verify -> abData[offset++] = 0x00; /* '\0' */ pin_verify -> ulDataLength = offset; /* APDU size */ length = sizeof(PIN_VERIFY_STRUCTURE) + offset -1; /* -1 because PIN_VERIFY_STRUCTURE contains the first byte of abData[] */ printf(" command:"); for (i=0; i<length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); printf("Enter your PIN: "); fflush(stdout); rv = SCardControl(hCard, verify_ioctl, bSendBuffer, length, bRecvBuffer, sizeof(bRecvBuffer), &length); { #ifndef S_SPLINT_S fd_set fd; #endif struct timeval timeout; FD_ZERO(&fd); FD_SET(STDIN_FILENO, &fd); /* stdin */ timeout.tv_sec = 0; /* timeout = 0.1s */ timeout.tv_usec = 100000; /* we only try to read stdin if the pinpad is on a keyboard * we do not read stdin for a SPR 532 for example */ if (select(1, &fd, NULL, NULL, &timeout) > 0) { /* read the fake digits */ char in[40]; /* 4 digits + \n + \0 */ (void)fgets(in, sizeof(in), stdin); printf("keyboard sent: %s", in); } else /* if it is not a keyboard */ printf("\n"); } printf(" card response:"); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n"); PCSC_ERROR_CONT(rv, "SCardControl") /* verify PIN dump */ printf("\nverify PIN dump: "); send_length = 5; memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF", send_length); for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); printf(" card response:"); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n"); PCSC_ERROR_EXIT(rv, "SCardTransmit") if ((2 == length) && (0x6C == bRecvBuffer[0])) { printf("\nverify PIN dump: "); send_length = 5; memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF", send_length); bSendBuffer[4] = bRecvBuffer[1]; for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); printf(" card response:"); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n"); PCSC_ERROR_EXIT(rv, "SCardTransmit") }
static void ContextThread(LPVOID newContext) { SCONTEXT * threadContext = (SCONTEXT *) newContext; int32_t filedes = threadContext->dwClientID; if (IsClientAuthorized(filedes, "access_pcsc", NULL) == 0) { Log1(PCSC_LOG_CRITICAL, "Rejected unauthorized PC/SC client"); goto exit; } else { Log1(PCSC_LOG_DEBUG, "Authorized PC/SC client"); } Log3(PCSC_LOG_DEBUG, "Thread is started: dwClientID=%d, threadContext @%p", threadContext->dwClientID, threadContext); while (1) { struct rxHeader header; int32_t ret = MessageReceive(&header, sizeof(header), filedes); if (ret != SCARD_S_SUCCESS) { /* Clean up the dead client */ Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); EHTryToUnregisterClientForEvent(filedes); goto exit; } if ((header.command > CMD_ENUM_FIRST) && (header.command < CMD_ENUM_LAST)) Log3(PCSC_LOG_DEBUG, "Received command: %s from client %d", CommandsText[header.command], filedes); switch (header.command) { /* pcsc-lite client/server protocol version */ case CMD_VERSION: { struct version_struct veStr; READ_BODY(veStr) Log3(PCSC_LOG_DEBUG, "Client is protocol version %d:%d", veStr.major, veStr.minor); veStr.rv = SCARD_S_SUCCESS; /* client and server use different protocol */ if ((veStr.major != PROTOCOL_VERSION_MAJOR) || (veStr.minor != PROTOCOL_VERSION_MINOR)) { Log3(PCSC_LOG_CRITICAL, "Client protocol is %d:%d", veStr.major, veStr.minor); Log3(PCSC_LOG_CRITICAL, "Server protocol is %d:%d", PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR); veStr.rv = SCARD_E_NO_SERVICE; } /* set the server protocol version */ veStr.major = PROTOCOL_VERSION_MAJOR; veStr.minor = PROTOCOL_VERSION_MINOR; /* send back the response */ WRITE_BODY(veStr) } break; case CMD_GET_READERS_STATE: { /* nothing to read */ #ifdef USE_USB /* wait until all readers are ready */ RFWaitForReaderInit(); #endif /* dump the readers state */ ret = MessageSend(readerStates, sizeof(readerStates), filedes); } break; case CMD_WAIT_READER_STATE_CHANGE: { struct wait_reader_state_change waStr; READ_BODY(waStr) /* add the client fd to the list */ EHRegisterClientForEvent(filedes); /* We do not send anything here. * Either the client will timeout or the server will * answer if an event occurs */ } break; case CMD_STOP_WAITING_READER_STATE_CHANGE: { struct wait_reader_state_change waStr; READ_BODY(waStr) /* add the client fd to the list */ waStr.rv = EHUnregisterClientForEvent(filedes); WRITE_BODY(waStr) } break; case SCARD_ESTABLISH_CONTEXT: { struct establish_struct esStr; SCARDCONTEXT hContext; READ_BODY(esStr) hContext = esStr.hContext; esStr.rv = SCardEstablishContext(esStr.dwScope, 0, 0, &hContext); esStr.hContext = hContext; if (esStr.rv == SCARD_S_SUCCESS) esStr.rv = MSGAddContext(esStr.hContext, threadContext); WRITE_BODY(esStr) } break; case SCARD_RELEASE_CONTEXT: { struct release_struct reStr; READ_BODY(reStr) reStr.rv = SCardReleaseContext(reStr.hContext); if (reStr.rv == SCARD_S_SUCCESS) reStr.rv = MSGRemoveContext(reStr.hContext, threadContext); WRITE_BODY(reStr) } break; case SCARD_CONNECT: { struct connect_struct coStr; SCARDHANDLE hCard; DWORD dwActiveProtocol; READ_BODY(coStr) coStr.szReader[sizeof(coStr.szReader)-1] = 0; hCard = coStr.hCard; dwActiveProtocol = coStr.dwActiveProtocol; if (IsClientAuthorized(filedes, "access_card", coStr.szReader) == 0) { Log2(PCSC_LOG_CRITICAL, "Rejected unauthorized client for '%s'", coStr.szReader); goto exit; } else { Log2(PCSC_LOG_DEBUG, "Authorized client for '%s'", coStr.szReader); } coStr.rv = SCardConnect(coStr.hContext, coStr.szReader, coStr.dwShareMode, coStr.dwPreferredProtocols, &hCard, &dwActiveProtocol); coStr.hCard = hCard; coStr.dwActiveProtocol = dwActiveProtocol; if (coStr.rv == SCARD_S_SUCCESS) coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard, threadContext); WRITE_BODY(coStr) } break; case SCARD_RECONNECT: { struct reconnect_struct rcStr; DWORD dwActiveProtocol; READ_BODY(rcStr) if (MSGCheckHandleAssociation(rcStr.hCard, threadContext)) goto exit; rcStr.rv = SCardReconnect(rcStr.hCard, rcStr.dwShareMode, rcStr.dwPreferredProtocols, rcStr.dwInitialization, &dwActiveProtocol); rcStr.dwActiveProtocol = dwActiveProtocol; WRITE_BODY(rcStr) } break; case SCARD_DISCONNECT: { struct disconnect_struct diStr; READ_BODY(diStr) if (MSGCheckHandleAssociation(diStr.hCard, threadContext)) goto exit; diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition); if (SCARD_S_SUCCESS == diStr.rv) diStr.rv = MSGRemoveHandle(diStr.hCard, threadContext); WRITE_BODY(diStr) } break; case SCARD_BEGIN_TRANSACTION: { struct begin_struct beStr; READ_BODY(beStr) if (MSGCheckHandleAssociation(beStr.hCard, threadContext)) goto exit; beStr.rv = SCardBeginTransaction(beStr.hCard); WRITE_BODY(beStr) } break; case SCARD_END_TRANSACTION: { struct end_struct enStr; READ_BODY(enStr) if (MSGCheckHandleAssociation(enStr.hCard, threadContext)) goto exit; enStr.rv = SCardEndTransaction(enStr.hCard, enStr.dwDisposition); WRITE_BODY(enStr) } break; case SCARD_CANCEL: { struct cancel_struct caStr; SCONTEXT * psTargetContext = NULL; READ_BODY(caStr) /* find the client */ (void)pthread_mutex_lock(&contextsList_lock); psTargetContext = (SCONTEXT *) list_seek(&contextsList, &caStr.hContext); (void)pthread_mutex_unlock(&contextsList_lock); if (psTargetContext != NULL) { uint32_t fd = psTargetContext->dwClientID; caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED); /* the client should not receive the event * notification now the waiting has been cancelled */ EHUnregisterClientForEvent(fd); } else caStr.rv = SCARD_E_INVALID_HANDLE; WRITE_BODY(caStr) } break; case SCARD_STATUS: { struct status_struct stStr; READ_BODY(stStr) if (MSGCheckHandleAssociation(stStr.hCard, threadContext)) goto exit; /* only hCard and return value are used by the client */ stStr.rv = SCardStatus(stStr.hCard, NULL, NULL, NULL, NULL, 0, NULL); WRITE_BODY(stStr) } break; case SCARD_TRANSMIT: { struct transmit_struct trStr; unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED]; unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED]; SCARD_IO_REQUEST ioSendPci; SCARD_IO_REQUEST ioRecvPci; DWORD cbRecvLength; READ_BODY(trStr) if (MSGCheckHandleAssociation(trStr.hCard, threadContext)) goto exit; /* avoids buffer overflow */ if ((trStr.pcbRecvLength > sizeof(pbRecvBuffer)) || (trStr.cbSendLength > sizeof(pbSendBuffer))) goto buffer_overflow; /* read sent buffer */ ret = MessageReceive(pbSendBuffer, trStr.cbSendLength, filedes); if (ret != SCARD_S_SUCCESS) { Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); goto exit; } ioSendPci.dwProtocol = trStr.ioSendPciProtocol; ioSendPci.cbPciLength = trStr.ioSendPciLength; ioRecvPci.dwProtocol = trStr.ioRecvPciProtocol; ioRecvPci.cbPciLength = trStr.ioRecvPciLength; cbRecvLength = sizeof pbRecvBuffer; trStr.rv = SCardTransmit(trStr.hCard, &ioSendPci, pbSendBuffer, trStr.cbSendLength, &ioRecvPci, pbRecvBuffer, &cbRecvLength); if (cbRecvLength > trStr.pcbRecvLength) /* The client buffer is not large enough. * The pbRecvBuffer buffer will NOT be sent a few * lines bellow. So no buffer overflow is expected. */ trStr.rv = SCARD_E_INSUFFICIENT_BUFFER; trStr.ioSendPciProtocol = ioSendPci.dwProtocol; trStr.ioSendPciLength = ioSendPci.cbPciLength; trStr.ioRecvPciProtocol = ioRecvPci.dwProtocol; trStr.ioRecvPciLength = ioRecvPci.cbPciLength; trStr.pcbRecvLength = cbRecvLength; WRITE_BODY(trStr) /* write received buffer */ if (SCARD_S_SUCCESS == trStr.rv) ret = MessageSend(pbRecvBuffer, cbRecvLength, filedes); } break; case SCARD_CONTROL: { struct control_struct ctStr; unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED]; unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED]; DWORD dwBytesReturned; READ_BODY(ctStr) if (MSGCheckHandleAssociation(ctStr.hCard, threadContext)) goto exit; /* avoids buffer overflow */ if ((ctStr.cbRecvLength > sizeof(pbRecvBuffer)) || (ctStr.cbSendLength > sizeof(pbSendBuffer))) { goto buffer_overflow; } /* read sent buffer */ ret = MessageReceive(pbSendBuffer, ctStr.cbSendLength, filedes); if (ret != SCARD_S_SUCCESS) { Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); goto exit; } dwBytesReturned = ctStr.dwBytesReturned; ctStr.rv = SCardControl(ctStr.hCard, ctStr.dwControlCode, pbSendBuffer, ctStr.cbSendLength, pbRecvBuffer, ctStr.cbRecvLength, &dwBytesReturned); ctStr.dwBytesReturned = dwBytesReturned; WRITE_BODY(ctStr) /* write received buffer */ if (SCARD_S_SUCCESS == ctStr.rv) ret = MessageSend(pbRecvBuffer, dwBytesReturned, filedes); } break; case SCARD_GET_ATTRIB: { struct getset_struct gsStr; DWORD cbAttrLen; READ_BODY(gsStr) if (MSGCheckHandleAssociation(gsStr.hCard, threadContext)) goto exit; /* avoids buffer overflow */ if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr)) goto buffer_overflow; cbAttrLen = gsStr.cbAttrLen; gsStr.rv = SCardGetAttrib(gsStr.hCard, gsStr.dwAttrId, gsStr.pbAttr, &cbAttrLen); gsStr.cbAttrLen = cbAttrLen; WRITE_BODY(gsStr) } break; case SCARD_SET_ATTRIB: { struct getset_struct gsStr; READ_BODY(gsStr) if (MSGCheckHandleAssociation(gsStr.hCard, threadContext)) goto exit; /* avoids buffer overflow */ if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr)) goto buffer_overflow; gsStr.rv = SCardSetAttrib(gsStr.hCard, gsStr.dwAttrId, gsStr.pbAttr, gsStr.cbAttrLen); WRITE_BODY(gsStr) } break; default: Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", header.command); goto exit; } /* MessageSend() failed */ if (ret != SCARD_S_SUCCESS) { /* Clean up the dead client */ Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); goto exit; } } buffer_overflow: Log2(PCSC_LOG_DEBUG, "Buffer overflow detected: %d", filedes); goto exit; wrong_length: Log2(PCSC_LOG_DEBUG, "Wrong length: %d", filedes); exit: (void)close(filedes); (void)MSGCleanupClient(threadContext); (void)pthread_exit((LPVOID) NULL); }