static int testCardFunctionality(SCARDCONTEXT ctx, const char *readerName) { SCARDHANDLE hCard; DWORD protocol; int errCount = 0; printf("Using reader \"%s\"\n\n", readerName); long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { delayMS(200); printf("--- Get Response tests ---\n"); errCount += testGetResponse(hCard); printf("\n--- Get Response tests within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testGetResponse(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Test reading a long file ---\n"); errCount += testLongFileRead(hCard); printf("\n--- Test reading a long file within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testLongFileRead(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Misc tests ---\n"); errCount += testMisc(hCard); ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardDisconnect", ret); } if (errCount == 0) printf("\nFunctional tests done, no errors\n"); else printf("\nFunctional tests done, %d errors\n", errCount); return 0; }
/* * Begin transaction. */ JNIEXPORT jint JNICALL GEN_FUNCNAME(Card_NativeEndTransaction) (JNIEnv *env, jobject _this, jint dispo) { SCARDHANDLE card; card = (SCARDHANDLE) (*env)->GetLongField(env, _this, CardField); return SCardEndTransaction(card, dispo); }
static int testTransaction(SCARDCONTEXT ctx, const char *readerName) { int returnValue = 0; SCARDHANDLE hCard; DWORD protocol; long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET_PASS(0x1) //-------1 if (SCARD_S_SUCCESS == ret) { delayMS(200); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET_PASS(0x2) //------1- ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET_PASS(0x2) //-----1-- ret = SCardEndTransaction(1111, SCARD_LEAVE_CARD); CHECK_PCSC_RET_FAIL(0x2) //-----1-- }
static UINT32 smartcard_EndTransaction_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, HCardAndDisposition_Call* call) { LONG status; Long_Return ret; status = ret.ReturnCode = SCardEndTransaction(operation->hCard, call->dwDisposition); smartcard_trace_long_return(smartcard, &ret, "EndTransaction"); return ret.ReturnCode; }
int Token::dump_primary(vector<BYTE> &res, DWORD id){ LONG lReturn; BYTE cont_number = 0; BYTE *pbSend, *pbRecv; DWORD dwRecv; const DWORD cdwRecv = 1024; const DWORD cdwSend = 128; // need to login if (0 != this->et72k_Login()) return 11; res.clear(); pbSend = new BYTE[cdwSend]; pbRecv = new BYTE[cdwRecv]; //begin transaction lReturn = SCardBeginTransaction(this->hCardHandle); if (SCARD_S_SUCCESS != lReturn){ cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl; return 20; } memset(pbSend, 0, cdwSend); memcpy(pbSend, s11, ls11); pbSend[14] = id; dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, ls11, NULL, pbRecv, &dwRecv); //send s11 with container id if (memcmp(pbRecv, noFile, 2) == 0){ //file not found delete[] pbRecv; delete[] pbSend; return 10; //no such container id } //cout << ">>>(s11) "; showarr(pbSend, ls11, ':'); //DEBUG //cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGET_PRIMARY, lcmdGET_PRIMARY, NULL, pbRecv, &dwRecv); //claim primary.key for (int i = 0; i < dwRecv - 2; i++) res.push_back(pbRecv[i]); //cout << ">>> "; showarr(cmdGET_MASKS, lcmdGET_MASKS, ':'); //DEBUG //cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG //End transaction SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD); delete[] pbRecv; delete[] pbSend; return 0; }
int Token::dump_name(vector<BYTE> &res, DWORD id){ LONG lReturn; BYTE cont_number = 0; BYTE *pbSend, *pbRecv; DWORD dwRecv; const DWORD cdwRecv = 1024; const DWORD cdwSend = 128; res.clear(); pbSend = new BYTE[cdwSend]; pbRecv = new BYTE[cdwRecv]; //begin transaction lReturn = SCardBeginTransaction(this->hCardHandle); if (SCARD_S_SUCCESS != lReturn){ cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl; return 20; } this->sendPreambula(); memset(pbSend, 0, cdwSend); memcpy(pbSend, s5, ls5); pbSend[14] = id; dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, ls6, NULL, pbRecv, &dwRecv); //send s6 with container id if (memcmp(pbRecv, noFile, 2) == 0){ //file not found delete[] pbRecv; delete[] pbSend; return 10; //no such container id } //cout << ">>>(s5) "; showarr(pbSend, ls5, ':'); //DEBUG //cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_ALL_name, lcmdGIVE_ALL_name, NULL, pbRecv, &dwRecv); //claim first 10 bytes of header.key for (int i = 0; i < dwRecv - 2 && pbRecv[i] != 0x00; i++) res.push_back(pbRecv[i]); //cout << ">>>(1st 10) "; showarr(cmdGIVE_ALL_name, lcmdGIVE_ALL_name, ':'); //DEBUG //cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG //End transaction SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD); delete[] pbRecv; delete[] pbSend; return 0; }
bool CPCSCClass::EndTransaction(DWORD EndDisposition) { RetCode = SCardEndTransaction(hCard,EndDisposition); if (RetCode != SCARD_S_SUCCESS) { mylog.AddToLogs(m_logobj,"error: SCardEndTransaction failed"); mylog.AddToLogs(m_logobj,TranslatePCSCError()); return false; } mylog.AddToLogs(m_logobj,"SCardEndTransaction Success"); return true; }
// // FUNCTION NAME: SIM_End_Transaction // // DESCRIPTION: this is a wrapper for pcsclite SCardEndTransaction 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: // None. // // NOTES: // - Possible extension will require additional parameters to be chosen by // the caller. // void SIM_End_Transaction(SCARDHANDLE hCard) { LONG rv; rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); switch(rv) { case SCARD_E_READER_UNAVAILABLE: { bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_READER_REMOVED); } case SCARD_E_SHARING_VIOLATION: { bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_SHARING_VIOLATION); } case SCARD_E_INVALID_HANDLE: { bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_INVALID_CONTEXT_HANDLER); } case SCARD_S_SUCCESS: { printf("TRANSACTION SUCCESSFULLY CLOSED.\n"); break; } default: { bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_WRONG_RETURN_VALUE); } } }
static UINT32 handle_EndTransaction(IRP* irp) { LONG status; SCARDCONTEXT hCard; DWORD dwDisposition = 0; stream_seek(irp->input, 0x20); stream_read_UINT32(irp->input, dwDisposition); stream_seek(irp->input, 0x0C); stream_read_UINT32(irp->input, hCard); status = SCardEndTransaction(hCard, dwDisposition); if (status != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status); else DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard); smartcard_output_alignment(irp, 8); return status; }
static uint32 handle_EndTransaction(IRP* irp) { LONG rv; SCARDCONTEXT hCard; DWORD dwDisposition = 0; stream_seek(irp->input, 0x20); stream_read_uint32(irp->input, dwDisposition); stream_seek(irp->input, 0x0C); stream_read_uint32(irp->input, hCard); rv = SCardEndTransaction(hCard, dwDisposition); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard); sc_output_alignment(irp, 8); return rv; }
bool QPCSCReader::endTransaction( Reset reset ) { return SCardEndTransaction( d->card, reset ) == SCARD_S_SUCCESS; }
void Token::list_containers(vector<string> &res){ LONG lReturn; BYTE cont_number = 0; BYTE *pbSend, *pbRecv; DWORD dwRecv; const DWORD cdwRecv = 1024; const DWORD cdwSend = 128; res.clear(); pbSend = new BYTE[cdwSend]; pbRecv = new BYTE[cdwRecv]; //begin transaction lReturn = SCardBeginTransaction(this->hCardHandle); if (SCARD_S_SUCCESS != lReturn){ cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl; return; } while (true){ this->sendPreambula(); memset(pbSend, 0, cdwSend); memcpy(pbSend, s4, 16); pbSend[14] = cont_number; dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, 16, NULL, pbRecv, &dwRecv); //send s4 with container number if (memcmp(pbRecv, noFile, 2) == 0) //file not found break; memset(pbSend, 0, cdwSend); memcpy(pbSend, s5, 18); pbSend[14] = cont_number; dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, 18, NULL, pbRecv, &dwRecv); //send s5 with container number dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_10, 10, NULL, pbRecv, &dwRecv); //claim first 10 bytes of container name DWORD container_name_len = pbRecv[3]; string container_name; int i = 4; while (pbRecv[i] != 0x00 && pbRecv[i] != 0x90){ container_name.append((char *)(pbRecv + i), 1); i++; } if (container_name_len > 6){ //received 10b without header with length in 4th byte memset(pbSend, 0, cdwSend); memcpy(pbSend, cmdGIVE_10, 10); pbSend[8] = 0x0a; //10b that we received pbSend[9] = container_name_len - pbSend[8] + 4; //the rest dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, 10, NULL, pbRecv, &dwRecv); container_name.append((char *)pbRecv, dwRecv - 2); } res.push_back(container_name); cont_number++; } //End transaction SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD); delete[] pbRecv; delete[] pbSend; }
long CardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) { return SCardEndTransaction(hCard, dwDisposition); }
int Token::dump_header(vector<BYTE> &res, DWORD id){ LONG lReturn; BYTE cont_number = 0; BYTE *pbSend, *pbRecv; DWORD dwRecv; const DWORD cdwRecv = 1024; const DWORD cdwSend = 128; res.clear(); pbSend = new BYTE[cdwSend]; pbRecv = new BYTE[cdwRecv]; //begin transaction lReturn = SCardBeginTransaction(this->hCardHandle); if (SCARD_S_SUCCESS != lReturn){ cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl; return 20; } this->sendPreambula(); memset(pbSend, 0, cdwSend); memcpy(pbSend, s6, ls6); pbSend[14] = id; dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, ls6, NULL, pbRecv, &dwRecv); //send s6 with container id if (memcmp(pbRecv, noFile, 2) == 0){ //file not found delete[] pbRecv; delete[] pbSend; return 10; //no such container id } //cout << ">>>(s6) "; showarr(pbSend, ls6, ':'); //DEBUG //cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_10, lcmdGIVE_10, NULL, pbRecv, &dwRecv); //claim first 10 bytes of header.key for (int i = 0; i < 0x0a; i++) res.push_back(pbRecv[i]); //cout << ">>>(1st 10) "; showarr(cmdGIVE_10, lcmdGIVE_10, ':'); //DEBUG //cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG DWORD header_len = (pbRecv[2] << 8) + pbRecv[3]; //length of header DWORD bytes_received = 0x0a; //now received const DWORD portion = 0xf5; //bytes claim with one request while (bytes_received < header_len){ memset(pbSend, 0, cdwSend); memcpy(pbSend, cmdGIVE_10, lcmdGIVE_10); pbSend[7] = bytes_received >> 8; pbSend[8] = bytes_received & 0xff; pbSend[9] = ((header_len - bytes_received + 4) > portion) ? portion : (header_len - bytes_received + 4); dwRecv = cdwRecv; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, lcmdGIVE_10, NULL, pbRecv, &dwRecv); bytes_received += pbSend[9]; for (int i = 0; i < pbSend[9]; i++) res.push_back(pbRecv[i]); //cout << ">>> "; showarr(pbSend, lcmdGIVE_10, ':'); //DEBUG //cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG } //End transaction SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD); delete[] pbRecv; delete[] pbSend; //cout << res << endl; //DEBUG return 0; }
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); }
static int testCardFunctionality(SCARDCONTEXT ctx, const char *readerName) { SCARDHANDLE hCard; DWORD protocol; int errCount = 0; printf("Using reader \"%s\"\n\n", readerName); printf("NOTE: make sure no-one else is accessing the card!\n\n"); long ret = SCardConnectA(ctx, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol); CHECK_PCSC_RET("SCardConnect", ret); if (SCARD_S_SUCCESS == ret) { delayMS(200); printf("--- SCardReconnect tests ---\n"); errCount += testScardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0); #ifdef _WIN32 printf("\n--- SCardState tests ---\n"); errCount += testSCardState(hCard); #endif printf("\n--- SCardStatus tests ---\n"); errCount += testSCardStatus(hCard); #ifndef MAC_OS_X printf("\n--- SCardGetAttrib tests ---\n"); errCount += testSCardGetAttrib(ctx, hCard); #endif printf("\n--- Get Response tests ---\n"); errCount += testGetResponse(hCard); printf("\n--- Get Response tests within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testGetResponse(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Test reading a long file ---\n"); errCount += testLongFileRead(hCard); printf("\n--- Test reading a long file within a transaction ---\n"); ret = SCardBeginTransaction(hCard); CHECK_PCSC_RET("SCardBeginTransaction", ret); errCount += testLongFileRead(hCard); ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardBeginTransaction", ret); printf("\n--- Misc tests ---\n"); errCount += testMisc(hCard); printf("\n--- Test ListReaders ---\n"); errCount += testListReaders(ctx); ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD); CHECK_PCSC_RET("SCardDisconnect", ret); } if (errCount == 0) printf("\nFunctional tests done, no errors\n"); else printf("\nFunctional tests done, %d errors\n", errCount); return 0; }
int main (int argc, const char *argv[]) { char *pin = 0; char *chal = 0; char *reader = 0; char *amount = 0; int getid = 0; int getotp = 0; int readernum = 0; int debug = 0; int listreader = 0; int hyphen = 0; int res; char c; SCARDCONTEXT ctx; SCARDHANDLE card; BYTE atr[MAX_ATR_SIZE]; DWORD atrlen; DWORD state; DWORD proto; DWORD temp; SCARD_IO_REQUEST recvpci; DWORD buflen; BYTE buf[256], cmd[256]; poptContext optCon; // context for parsing command-line options const struct poptOption optionsTable[] = { {"id", 'i', POPT_ARG_NONE, &getid, 0, "Report card ID", 0}, {"pin", 'p', POPT_ARG_STRING, &pin, 0, "PIN", "6 to 12 digits"}, {"otp", 'o', POPT_ARG_NONE, &getotp, 0, "Get OTP", 0}, {"reference", 'c', POPT_ARG_STRING, &chal, 0, "Challenge/response or account reference", "Up to 8 digit reference/account"}, {"amount", 'a', POPT_ARG_STRING, &amount, 0, "", "Amount pounds.pence"}, {"reader", 'r', POPT_ARG_INT, &readernum, 0, "Which reader to use", "Index number"}, {"list", 'l', POPT_ARG_NONE, &listreader, 0, "List readers", 0}, {"hyphen", 'h', POPT_ARG_NONE, &hyphen, 0, "Hyphenate OTP or C/R responses", 0}, {"debug", 'v', POPT_ARG_NONE, &debug, 0, "Debug output", 0}, POPT_AUTOHELP {NULL, 0, 0, NULL, 0} }; optCon = poptGetContext (NULL, argc, argv, optionsTable, 0); //poptSetOtherOptionHelp (optCon, ""); /* Now do options processing, get portname */ if ((c = poptGetNextOpt (optCon)) < -1) { /* an error occurred during option processing */ fprintf (stderr, "%s: %s\n", poptBadOption (optCon, POPT_BADOPTION_NOALIAS), poptStrerror (c)); return 1; } if (poptPeekArg (optCon)) { poptPrintUsage (optCon, stderr, 0); return 2; } if ((res = SCardEstablishContext (SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx)) != SCARD_S_SUCCESS) errx (1, "Can't establish context for reading cards (%s)", pcsc_stringify_error (res)); { // list the readers int rn = 0; char *r, *e; if ((res = SCardListReaders (ctx, NULL, NULL, &temp)) != SCARD_S_SUCCESS) errx (1, "Cannot get reader list (%s)", pcsc_stringify_error (res)); if (!(r = malloc (temp))) errx (1, "Cannot allocated %d bytes for reader list", (int) temp); if ((res = SCardListReaders (ctx, NULL, r, &temp)) != SCARD_S_SUCCESS) errx (1, "Cannot list readers (%s)", pcsc_stringify_error (res)); e = r + temp; while (*r && r < e) { if (rn == readernum) reader = r; if (listreader) printf ("%d: %s\n", rn, r); r += strlen (r) + 1; rn++; } // not freed as reader is pointer into r. } if (!reader) errx (1, "Reader %d does not exist", readernum); if (debug) fprintf (stderr, "Reader: %s\n", reader); // connect to card if ((res = SCardConnect (ctx, reader, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &card, &proto)) != SCARD_S_SUCCESS) errx (1, "Cannot connect to %s (%s)", reader, pcsc_stringify_error (res)); if (debug) fprintf (stderr, "Active protocol %X\n", (int) proto); if ((res = SCardBeginTransaction (card)) != SCARD_S_SUCCESS) errx (1, "Cannot start transaction (%s)", pcsc_stringify_error (res)); atrlen = sizeof (atr); if ((res = SCardStatus (card, 0, &temp, &state, &proto, atr, &atrlen)) != SCARD_S_SUCCESS) errx (1, "Cannot get card status (%s)", pcsc_stringify_error (res)); if (debug) fprintf (stderr, "ATR len %d state %X\n", (int) atrlen, (int) state); { // get basic data BYTE datareq[] = { 0x00, 0xA4, 0x04, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x80, 0x02 }; // initial data request buflen = sizeof (buf); if (debug) dump ('>', sizeof (datareq), datareq); if ((res = SCardTransmit (card, SCARD_PCI_T0, datareq, sizeof (datareq), &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send initial request for data (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != 2 || buf[0] != 0x61) errx (1, "Unexpected response to data request"); } cmd[0] = 0x0; cmd[1] = 0xC0; cmd[2] = 0; cmd[3] = 0; cmd[4] = buf[1]; buflen = sizeof (buf); if (debug) dump ('>', 5, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed get initial data (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != cmd[4] + 2) errx (1, "Did not get right data length %d!=%d", (int) buflen, cmd[4]); cmd[0] = 0x80; cmd[1] = 0xA8; cmd[2] = 0x00; cmd[3] = 0x00; cmd[4] = 0x02; cmd[5] = 0x83; cmd[6] = 0x00; buflen = sizeof (buf); if (debug) dump ('>', 7, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 7, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed get data (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != 2 || buf[0] != 0x61) errx (1, "Bad response\n"); cmd[0] = 0x00; cmd[1] = 0xC0; cmd[2] = 0x00; cmd[3] = 0x00; cmd[4] = buf[1]; buflen = sizeof (buf); if (debug) dump ('>', 5, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send data (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (getid) { // card number int n = 0; cmd[0] = 0x00; cmd[1] = 0xB2; cmd[2] = 0x02; cmd[3] = 0x0C; cmd[4] = 0x00; buflen = sizeof (buf); if (debug) dump ('>', 5, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send data (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != 2 || buf[0] != 0x6C) errx (1, "Unexpected response to data request"); cmd[4] = buf[1]; buflen = sizeof (buf); if (debug) dump ('>', 5, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed get initial data (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != cmd[4] + 2 || buflen < 12) errx (1, "Did not get right data length %d!=%d", (int) buflen, cmd[4]); for (n = 4; n < 12; n++) printf ("%02X", buf[n]); printf ("\n"); } // send PIN if needed if (pin && (getotp || chal || amount || debug)) { // send PIN char *p = pin; int n = 0; cmd[0] = 0; cmd[1] = 0x20; cmd[2] = 0x00; cmd[3] = 0x80; cmd[4] = 8; cmd[5] = 0x24; while (*p && n < 14) { if (isdigit (*p)) { cmd[6 + n / 2] = (cmd[6 + n / 2] << 4) + (*p - '0'); n++; } p++; } while (n < 14) { cmd[6 + n / 2] = (cmd[6 + n / 2] << 4) + 0xF; n++; } buflen = sizeof (buf); if (debug) dump ('>', 13, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 13, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send PIN (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != 2 || buf[0] != 0x90 || buf[1]) errx (1, "PIN failed"); } if (getotp || chal || amount) { // OTP unsigned char req[29] = { 0 }; req[14] = 0x80; req[21] = req[22] = req[23] = 1; if (chal) { int n = 0, p; for (p = 0; chal[p]; p++) if (isdigit (chal[p])) n++; for (p = 0; chal[p] && n; p++) if (isdigit (chal[p])) { n--; if (n < 8) req[28 - n / 2] |= ((chal[p] & 0xF) << ((n & 1) ? 4 : 0)); } } if (amount) { int n = 0, p; for (p = 0; amount[p]; p++) if (isdigit (amount[p])) n++; for (p = 0; amount[p] && n; p++) if (isdigit (amount[p])) { n--; if (n < 12) req[5 - n / 2] |= ((amount[p] & 0xF) << ((n & 1) ? 4 : 0)); } } buflen = sizeof (buf); buf[0] = 0x80; buf[1] = 0xAE; buf[2] = 0x80; buf[3] = 0x00; buf[4] = sizeof (req); memcpy (buf + 5, req, sizeof (req)); if (debug) dump ('>', sizeof (req) + 5, buf); if ((res = SCardTransmit (card, SCARD_PCI_T0, buf, sizeof (req) + 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != 2 || buf[0] != 0x61) errx (1, "Failed to get OTP"); cmd[0] = 0x00; cmd[1] = 0xC0; cmd[2] = 0x00; cmd[3] = 0x00; cmd[4] = buf[1]; buflen = sizeof (buf); if (debug) dump ('>', 5, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != 22) errx (1, "Bad OTP response"); { unsigned long res = ((1 << 25) | (buf[4] << 17) | ((buf[10] & 0x01) << 16) | (buf[11] << 8) | buf[12]); printf ("%08lu\n", res); } // Advance OTP to next number buf[0] = 0x80; buf[1] = 0xAE; buf[2] = 0x00; buf[3] = 0x00; buf[4] = sizeof (req) + 2; buf[5] = 0x5A; buf[6] = 0x33; memcpy (buf + 7, req, sizeof (req)); buflen = sizeof (buf); if (debug) dump ('>', sizeof (req) + 7, buf); if ((res = SCardTransmit (card, SCARD_PCI_T0, buf, sizeof (req) + 7, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); if (buflen != 2 || buf[0] != 0x61) errx (1, "Failed to get OTP"); cmd[0] = 0x00; cmd[1] = 0xC0; cmd[2] = 0x00; buflen = sizeof (buf); if (debug) dump ('>', 5, cmd); if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS) errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res)); if (debug) dump ('<', buflen, buf); } // Done if ((res = SCardEndTransaction (card, SCARD_UNPOWER_CARD)) != SCARD_S_SUCCESS) errx (1, "Cannot end transaction (%s)", pcsc_stringify_error (res)); if ((res = SCardReleaseContext (ctx)) != SCARD_S_SUCCESS) errx (1, "Cant release context (%s)", pcsc_stringify_error (res)); return 0; }
int Token::et72k_Login(){ LONG lReturn; const DWORD buff_size = 1024; DWORD dwRecv; int ret = 1; BYTE challenge8[8], rte_data20[20], cmd8011t[15]; if (strlen(this->upass) == 0){ if (this->debug) cout << "[*] No user password specified, but have to" << endl; return 21; } //if (this->loggedin) return 0; BYTE* pbRecv = new BYTE[buff_size]; lReturn = SCardBeginTransaction(this->hCardHandle); if (SCARD_S_SUCCESS != lReturn){ cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl; return 20; } this->sendPreambula(); dwRecv = buff_size; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, s8, ls8, NULL, pbRecv, &dwRecv); //send s8 dwRecv = buff_size; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, s9, ls9, NULL, pbRecv, &dwRecv); //send s9 dwRecv = buff_size; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, s10, ls10, NULL, pbRecv, &dwRecv); //send s10 //get 20bytes RTE const memset(pbRecv, 0, buff_size); dwRecv = buff_size; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_RTE20, lcmdGIVE_RTE20, NULL, pbRecv, &dwRecv); memcpy(rte_data20, pbRecv, 20); if (this->debug){ cout << "[*] token RTE data: "; showarr(rte_data20, 20, ':'); } //get challenge memset(pbRecv, 0, buff_size); dwRecv = buff_size; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmd8017, lcmd8017, NULL, pbRecv, &dwRecv); memcpy(challenge8, pbRecv, 8); if (this->debug){ cout << "[*] token challenge: "; showarr(challenge8, 8, ':'); } //authenticate this->coumpute_authcode(challenge8, rte_data20); if (this->debug){ cout << "[*] app response: "; showarr(challenge8, 8, ':'); } memcpy(cmd8011t, cmd8011, lcmd8011); memcpy(cmd8011t + 7, challenge8, 8); memset(pbRecv, 0, buff_size); dwRecv = buff_size; SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmd8011t, lcmd8011, NULL, pbRecv, &dwRecv); if (this->debug){ cout << "[*] et72k_Login finished with: "; showarr(pbRecv, 2, ':'); } if (memcmp(pbRecv, resOK, 2) == 0){ ret = 0; //this->loggedin = true; } //End transaction SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD); delete[] pbRecv; return ret; }