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 UINT32 smartcard_Control_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, Control_Call* call) { LONG status; Control_Return ret; IRP* irp = operation->irp; ret.cbOutBufferSize = call->cbOutBufferSize; ret.pvOutBuffer = (BYTE*) malloc(call->cbOutBufferSize); if (!ret.pvOutBuffer) return SCARD_E_NO_MEMORY; status = ret.ReturnCode = SCardControl(operation->hCard, call->dwControlCode, call->pvInBuffer, call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize); smartcard_trace_control_return(smartcard, &ret); status = smartcard_pack_control_return(smartcard, irp->output, &ret); if (status != SCARD_S_SUCCESS) return status; if (call->pvInBuffer) free(call->pvInBuffer); if (ret.pvOutBuffer) free(ret.pvOutBuffer); return ret.ReturnCode; }
int transmitVerifyPinAPDUviaPCSC(struct p11Slot_t *slot, unsigned char pinformat, unsigned char minpinsize, unsigned char maxpinsize, unsigned char pinblockstring, unsigned char pinlengthformat, unsigned char *capdu, size_t capdu_len, unsigned char *rapdu, size_t rapdu_len) { LONG rc; DWORD lenr; PIN_VERIFY_DIRECT_STRUCTURE_t verify; FUNC_CALLED(); if (!slot->card) { FUNC_FAILS(-1, "No card handle"); } verify.bTimeOut = 0x00; verify.bTimeOut2 = 0x00; verify.bmFormatString = pinformat; verify.bmPINBlockString = pinblockstring; verify.bmPINLengthFormat = pinlengthformat; verify.wPINMaxExtraDigit = (minpinsize << 8) | maxpinsize; /* * Bit 7-3: RFU * Bit 2: Timout occurred * Bit 1: Validation Key pressed * Bit 0: Max size reached */ verify.bEntryValidationCondition = 0x02; verify.bNumberMessage = 0x01; verify.wLangID = 0x0904; verify.bMsgIndex = 0; verify.bTeoPrologue[0]= 0; verify.bTeoPrologue[1]= 0; verify.bTeoPrologue[2]= 0; verify.ulDataLength = capdu_len; memcpy(verify.abData, capdu, capdu_len); lenr = rapdu_len; rc = SCardControl(slot->card, slot->hasFeatureVerifyPINDirect, &verify, 18 + capdu_len + 1, rapdu, rapdu_len, &lenr); #ifdef DEBUG debug("SCardControl (VERIFY_PIN_DIRECT): %s\n", pcsc_error_to_string(rc)); #endif if (rc != SCARD_S_SUCCESS) { FUNC_FAILS(-1, "SCardControl failed"); } FUNC_RETURNS(lenr); }
/* * Send control bytes. */ JNIEXPORT jbyteArray JNICALL GEN_FUNCNAME(Card_NativeControl) (JNIEnv *env, jobject _this, jint jcc, jbyteArray jin, jint joff, jint jlen) { SCARDHANDLE card; unsigned char *cin; jboolean isCopy; unsigned char cout[RECEIVE_BUFFER_SIZE]; DWORD clen = RECEIVE_BUFFER_SIZE; jbyteArray jout; LONG rv; card = (SCARDHANDLE) (*env)->GetLongField(env, _this, CardField); cin = (*env)->GetByteArrayElements(env, jin, &isCopy); /* #ifndef WIN32 rv = SCardControl(card, cin + joff, jlen, cout, &clen); #else JPCSC_LOG(("NativeControl()-win32: control code 0x%x 0x%x\n", jcc, SCARD_CTL_CODE(jcc))); rv = SCardControl(card, SCARD_CTL_CODE(jcc), cin + joff, jlen, cout, clen, &clen); #endif */ #if defined(WIN32) || defined(HAVE_SCARD_ATTRIBUTES) || !defined(USE_SCARD_CONTROL_112) rv = SCardControl(card, SCARD_CTL_CODE(jcc), cin + joff, jlen, cout, clen, &clen); #else rv = SCardControl(card, cin + joff, jlen, cout, &clen); #endif /* defined(WIN32) || defined(HAVE_SCARD_ATTRIBUTES) */ JPCSC_LOG(("NativeControl(): returns 0x%x\n", rv)); (*env)->ReleaseByteArrayElements(env, jin, cin, JNI_ABORT); if (rv != SCARD_S_SUCCESS) { pcscex_throw(env, "Card.Control() failed", rv); return NULL; } jout = (*env)->NewByteArray(env, clen); (*env)->SetByteArrayRegion(env, jout, 0, clen, cout); return jout; }
static LONG SCR_SCardInit(LPCTSTR szPinPadDll, LPCTSTR szReader, DWORD version, SCR_SupportConstants * supported) { LONG rv; unsigned char sendbuf[256]; unsigned char recvbuf[2]; char szTemp[32]; DWORD dwRecvLength; struct tTLV tlv; memset(szTemp, 0, sizeof(szTemp)); memset(sendbuf, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); dwRecvLength = sizeof(recvbuf); /* Make TLV buffer */ TLVInit(&tlv, sendbuf, sizeof(sendbuf)); TLVNext(&tlv, 0x01); /* Function ID */ sprintf(szTemp, "%ld", SCR_INIT_ID); TLVAddBuffer(&tlv, (u8 *) szTemp, strlen(szTemp)); TLVNext(&tlv, 0x02); /* PinPad Dll */ TLVAddBuffer(&tlv, (u8 *) szPinPadDll, strlen(szPinPadDll)); TLVNext(&tlv, 0x03); /* Reader Name */ TLVAddBuffer(&tlv, (u8 *) szReader, strlen(szReader)); TLVNext(&tlv, 0x04); /* Version */ sprintf(szTemp, "%ld", version); TLVAddBuffer(&tlv, (u8 *) szTemp, strlen(szTemp)); #ifdef HAVE_PCSC_OLD rv = SCardControl(SCR_CARD_HANDLE, sendbuf, TLVLen(&tlv), recvbuf, &dwRecvLength); #else rv = SCardControl(SCR_CARD_HANDLE, 0, sendbuf, TLVLen(&tlv), recvbuf, dwRecvLength, &dwRecvLength); #endif if (dwRecvLength > 0) { *supported = recvbuf[0]; } else { rv = SC_ERROR_UNKNOWN_DATA_RECEIVED; } return rv; }
int PCSCv2Part10_find_TLV_property_by_tag_from_hcard(SCARDHANDLE hCard, int property, int * value) { unsigned char buffer[MAX_BUFFER_SIZE]; LONG rv; DWORD length; unsigned int i; PCSC_TLV_STRUCTURE *pcsc_tlv; DWORD properties_in_tlv_ioctl; int found; rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, buffer, sizeof buffer, &length); if (rv != SCARD_S_SUCCESS) return -1; /* get the number of elements instead of the complete size */ length /= sizeof(PCSC_TLV_STRUCTURE); pcsc_tlv = (PCSC_TLV_STRUCTURE *)buffer; found = 0; for (i = 0; i < length; i++) { if (FEATURE_GET_TLV_PROPERTIES == pcsc_tlv[i].tag) { properties_in_tlv_ioctl = ntohl(pcsc_tlv[i].value); found = 1; } } if (! found) return -3; rv= SCardControl(hCard, properties_in_tlv_ioctl, NULL, 0, buffer, sizeof buffer, &length); if (rv != SCARD_S_SUCCESS) return -1; return PCSCv2Part10_find_TLV_property_by_tag_from_buffer(buffer, length, property, value); }
bool acr122_led_red (nfc_device *pnd, bool bOn) { uint8_t abtLed[9] = { 0xFF, 0x00, 0x40, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00 }; uint8_t abtBuf[2]; DWORD dwBufLen = sizeof (abtBuf); (void) bOn; if (DRIVER_DATA (pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) { return (SCardControl (DRIVER_DATA (pnd)->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtLed, sizeof (abtLed), abtBuf, dwBufLen, &dwBufLen) == SCARD_S_SUCCESS); } else { return (SCardTransmit (DRIVER_DATA (pnd)->hCard, &(DRIVER_DATA (pnd)->ioCard), abtLed, sizeof (abtLed), NULL, abtBuf, &dwBufLen) == SCARD_S_SUCCESS); } }
long CardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned) { #ifndef __OLD_PCSC_API__ long lRet = SCardControl(hCard, dwControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned); //printf("SCardControl()\n"); return lRet; #else long lRet = SCardControl(hCard, (const unsigned char *) lpInBuffer, nInBufferSize, (unsigned char*) lpOutBuffer, lpBytesReturned); //printf("SCardControl()\n"); return lRet; #endif }
bool edna_emulator::transceive_control(SCARDHANDLE reader, const bytestring& cmd, bytestring& rdata) { DWORD pcsc_rv; DWORD rlen; rdata.resize(512); if ((pcsc_rv = SCardControl(reader, IOCTL_CCID_ESCAPE_DIRECT, cmd.const_byte_str(), cmd.size(), rdata.byte_str(), 512, &rlen)) != SCARD_S_SUCCESS) { ERROR_MSG("Failed to exchange control command (0x%08X)", pcsc_rv); SCardDisconnect(reader, SCARD_UNPOWER_CARD); SCardReleaseContext(pcsc_context); return false; } rdata.resize(rlen); return true; }
char * acr122_firmware (nfc_device *pnd) { uint8_t abtGetFw[5] = { 0xFF, 0x00, 0x48, 0x00, 0x00 }; uint32_t uiResult; static char abtFw[11]; DWORD dwFwLen = sizeof (abtFw); memset (abtFw, 0x00, sizeof (abtFw)); if (DRIVER_DATA (pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) { uiResult = SCardControl (DRIVER_DATA (pnd)->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtGetFw, sizeof (abtGetFw), (uint8_t *) abtFw, dwFwLen-1, &dwFwLen); } else { uiResult = SCardTransmit (DRIVER_DATA (pnd)->hCard, &(DRIVER_DATA (pnd)->ioCard), abtGetFw, sizeof (abtGetFw), NULL, (uint8_t *) abtFw, &dwFwLen); } if (uiResult != SCARD_S_SUCCESS) { log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "No ACR122 firmware received, Error: %08x", uiResult); } return abtFw; }
void OmnikeyXX21ReaderUnit::getT_CL_ISOType(bool& isTypeA, bool& isTypeB) { unsigned char outBuffer[64]; DWORD dwOutBufferSize; unsigned char inBuffer[2]; DWORD dwInBufferSize; DWORD dwBytesReturned; DWORD dwControlCode = CM_IOCTL_GET_SET_RFID_BAUDRATE; DWORD dwStatus; memset(outBuffer, 0x00, sizeof(outBuffer)); dwOutBufferSize = sizeof(outBuffer); dwInBufferSize = sizeof(inBuffer); dwBytesReturned = 0; inBuffer[0] = 0x01; // Version of command inBuffer[1] = 0x00; // Get asymmetric baud rate information isTypeA = false; isTypeB = false; dwStatus = SCardControl(getHandle(), dwControlCode, (LPVOID)inBuffer, dwInBufferSize, (LPVOID)outBuffer, dwOutBufferSize, &dwBytesReturned); if (dwStatus == SCARD_S_SUCCESS && dwBytesReturned >= 10) { switch (outBuffer[9]) { case 0x04: isTypeA = true; break; case 0x08: isTypeB = true; break; } } }
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 uint32 handle_Control(IRP* irp) { LONG rv; SCARDCONTEXT hContext; SCARDHANDLE hCard; uint32 map[3]; uint32 controlCode; uint32 controlFunction; BYTE *recvBuffer = NULL, *sendBuffer = NULL; uint32 recvLength; DWORD nBytesReturned; DWORD outBufferSize; stream_seek(irp->input, 0x14); stream_read_uint32(irp->input, map[0]); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, map[1]); stream_read_uint32(irp->input, controlCode); stream_read_uint32(irp->input, recvLength); stream_read_uint32(irp->input, map[2]); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, outBufferSize); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, hContext); stream_seek(irp->input, 0x4); stream_read_uint32(irp->input, hCard); /* Translate Windows SCARD_CTL_CODE's to corresponding local code */ if (WIN_CTL_DEVICE_TYPE(controlCode) == WIN_FILE_DEVICE_SMARTCARD) { controlFunction = WIN_CTL_FUNCTION(controlCode); controlCode = SCARD_CTL_CODE(controlFunction); } DEBUG_SCARD("controlCode: 0x%08x", (unsigned) controlCode); if (map[2] & SCARD_INPUT_LINKED) { /* read real input size */ stream_read_uint32(irp->input, recvLength); recvBuffer = xmalloc(recvLength); if (!recvBuffer) return sc_output_return(irp, SCARD_E_NO_MEMORY); stream_read(irp->input, recvBuffer, recvLength); } nBytesReturned = outBufferSize; sendBuffer = xmalloc(outBufferSize); if (!sendBuffer) return sc_output_return(irp, SCARD_E_NO_MEMORY); rv = SCardControl(hCard, (DWORD) controlCode, recvBuffer, (DWORD) recvLength, sendBuffer, (DWORD) outBufferSize, &nBytesReturned); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success (out: %u bytes)", (unsigned) nBytesReturned); stream_write_uint32(irp->output, (uint32) nBytesReturned); stream_write_uint32(irp->output, 0x00000004); stream_write_uint32(irp->output, nBytesReturned); if (nBytesReturned > 0) { stream_write(irp->output, sendBuffer, nBytesReturned); sc_output_repos(irp, nBytesReturned); } sc_output_alignment(irp, 8); xfree(recvBuffer); xfree(sendBuffer); return rv; }
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv) { SCARDHANDLE hCard; SCARDCONTEXT hContext; SCARD_READERSTATE rgReaderStates[1]; DWORD dwReaderLen, dwState, dwProt, dwAtrLen; DWORD dwPref, dwReaders = 0; char *pcReader = 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] = {0}; SCARD_IO_REQUEST ioRecvPci = *SCARD_PCI_T0; /* use a default value */ const 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]; char *r; printf("Enter the reader number\t\t: "); r = fgets(input, sizeof(input), stdin); if (NULL == r) iReader = -1; else iReader = atoi(input); 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; } /* APDU select file */ printf("Select file:"); send_length = 7; memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length); for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, pioSendPci, bSendBuffer, send_length, &ioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); 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) { int valid = 1; /* valid value by default */ long value; printf("Vendor IFD version\t\t: "); if (dwBufLen == sizeof(DWORD)) value = buf.as_DWORD; else { if (dwBufLen == sizeof(uint32_t)) value = buf.as_uint32_t; else { printf(RED "Unsupported size\n" NORMAL); valid = 0; /* invalid value */ } } if (valid) { int M = (value & 0xFF000000) >> 24; /* Major */ int m = (value & 0x00FF0000) >> 16; /* Minor */ int b = (value & 0x0000FFFF); /* build */ printf(GREEN "%d.%d.%d\n" NORMAL, M, m, b); } }
QPCSCReader::QPCSCReader( const QString &reader, QPCSC *parent ) : QObject( parent ) , d( new QPCSCReaderPrivate( parent->d ) ) { d->reader = reader.toUtf8(); d->state.szReader = d->reader.constData(); if( !d->updateState() ) return; /* Use DIRECT mode only if there is no card in the reader */ if( !isPresent() ) { #ifndef Q_OS_WIN /* Apple 10.5.7 and pcsc-lite previous to v1.5.5 do not support 0 as protocol identifier */ DWORD proto = SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1; #else DWORD proto = 0; #endif LONG rv = SCardConnect( d->d->context, d->state.szReader, SCARD_SHARE_DIRECT, proto, &d->card, &d->proto ); // Assume that there is a card in the reader in shared mode if direct communcation failed if( rv == LONG(SCARD_E_SHARING_VIOLATION) && !connect() ) return; } else if( !connect() ) return; d->friendlyName = d->attrib( SCARD_ATTR_DEVICE_FRIENDLY_NAME_A ); #if 0 qDebug() << "SCARD_ATTR_DEVICE_FRIENDLY_NAME:" << d->attrib( SCARD_ATTR_DEVICE_FRIENDLY_NAME_A ); qDebug() << "SCARD_ATTR_DEVICE_SYSTEM_NAME:" << d->attrib( SCARD_ATTR_DEVICE_SYSTEM_NAME_A ); qDebug() << "SCARD_ATTR_DEVICE_UNIT:" << d->attrib( SCARD_ATTR_DEVICE_UNIT ); qDebug() << "SCARD_ATTR_VENDOR_IFD_SERIAL_NO:" << d->attrib( SCARD_ATTR_VENDOR_IFD_SERIAL_NO ); qDebug() << "SCARD_ATTR_VENDOR_IFD_TYPE:" << d->attrib( SCARD_ATTR_VENDOR_IFD_TYPE ); qDebug() << "SCARD_ATTR_VENDOR_IFD_VERSION:" << d->attrib( SCARD_ATTR_VENDOR_IFD_VERSION ); qDebug() << "SCARD_ATTR_VENDOR_NAME:" << d->attrib( SCARD_ATTR_VENDOR_NAME ); #endif DWORD size = 0; BYTE feature[256]; LONG rv = SCardControl( d->card, CM_IOCTL_GET_FEATURE_REQUEST, 0, 0, feature, sizeof(feature), &size ); if( rv == SCARD_S_SUCCESS && (size % sizeof(PCSC_TLV_STRUCTURE)) == 0 ) { size /= sizeof(PCSC_TLV_STRUCTURE); PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature; for( DWORD i = 0; i < size; i++ ) d->ioctl[DRIVER_FEATURES(pcsc_tlv[i].tag)] = ntohl( pcsc_tlv[i].value ); } if( DWORD ioctl = d->ioctl.value(FEATURE_GET_TLV_PROPERTIES) ) { DWORD size = 0; BYTE recv[256]; rv = SCardControl( d->card, ioctl, 0, 0, recv, sizeof(recv), &size ); unsigned char *p = recv; while( DWORD(p-recv) < size ) { int tag = *p++, len = *p++, value = -1; switch( len ) { case 1: value = *p; break; case 2: value = *p + (*(p+1)<<8); break; case 4: value = *p + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24); break; default: break; } p += len; d->properties[Properties(tag)] = value; } } if( DWORD ioctl = d->ioctl.value(FEATURE_IFD_PIN_PROPERTIES) ) { DWORD size = 0; BYTE recv[256]; DWORD rv = SCardControl( d->card, ioctl, 0, 0, recv, sizeof(recv), &size ); if( rv == SCARD_S_SUCCESS ) { PIN_PROPERTIES_STRUCTURE *caps = (PIN_PROPERTIES_STRUCTURE *)recv; d->display = caps->wLcdLayout > 0; } } disconnect(); }
int acr122_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout) { // FIXME: timeout is not handled (void) timeout; // Make sure the command does not overflow the send buffer if (szData > ACR122_COMMAND_LEN) { pnd->last_error = NFC_EINVARG; return pnd->last_error; } // Prepare and transmit the send buffer const size_t szTxBuf = szData + 6; uint8_t abtTxBuf[ACR122_WRAP_LEN + ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00, szData + 1, 0xD4 }; memcpy (abtTxBuf + 6, pbtData, szData); LOG_HEX ("TX", abtTxBuf, szTxBuf); DRIVER_DATA (pnd)->szRx = 0; DWORD dwRxLen = sizeof (DRIVER_DATA (pnd)->abtRx); if (DRIVER_DATA (pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) { /* * In this communication mode, we directly have the response from the * PN532. Save it in the driver data structure so that it can be retrieved * in ac122_receive(). * * Some devices will never enter this state (e.g. Touchatag) but are still * supported through SCardTransmit calls (see bellow). * * This state is generaly reached when the ACR122 has no target in it's * field. */ if (SCardControl (DRIVER_DATA (pnd)->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtTxBuf, szTxBuf, DRIVER_DATA (pnd)->abtRx, ACR122_RESPONSE_LEN, &dwRxLen) != SCARD_S_SUCCESS) { pnd->last_error = NFC_EIO; return pnd->last_error; } } else { /* * In T=0 mode, we receive an acknoledge from the MCU, in T=1 mode, we * receive the response from the PN532. */ if (SCardTransmit (DRIVER_DATA (pnd)->hCard, &(DRIVER_DATA (pnd)->ioCard), abtTxBuf, szTxBuf, NULL, DRIVER_DATA (pnd)->abtRx, &dwRxLen) != SCARD_S_SUCCESS) { pnd->last_error = NFC_EIO; return pnd->last_error; } } if (DRIVER_DATA (pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_T0) { /* * Check the MCU response */ // Make sure we received the byte-count we expected if (dwRxLen != 2) { pnd->last_error = NFC_EIO; return pnd->last_error; } // Check if the operation was successful, so an answer is available if (DRIVER_DATA (pnd)->abtRx[0] == SCARD_OPERATION_ERROR) { pnd->last_error = NFC_EIO; return pnd->last_error; } } else { DRIVER_DATA (pnd)->szRx = dwRxLen; } return NFC_SUCCESS; }
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; }
static LONG SCR_SCardPIN(long lAction, LPCTSTR szPinPadDll, const SCR_Card * pCard, BYTE pinID, const SCR_PinUsage * pUsage, const SCR_Application * pApp, BYTE * pCardStatus) { LONG rv; unsigned char sendbuf[256]; unsigned char recvbuf[2]; char szTemp[32]; DWORD dwRecvLength; struct tTLV tlv; memset(szTemp, 0, sizeof(szTemp)); memset(recvbuf, 0, sizeof(recvbuf)); dwRecvLength = sizeof(recvbuf); /* Make TLV buffer */ TLVInit(&tlv, sendbuf, sizeof(sendbuf)); TLVNext(&tlv, 0x01); /* Function ID */ sprintf(szTemp, "%ld", lAction); TLVAddBuffer(&tlv, (u8 *) szTemp, strlen(szTemp)); TLVNext(&tlv, 0x02); /* PinPad Dll */ TLVAddBuffer(&tlv, (u8 *) szPinPadDll, strlen(szPinPadDll)); TLVNext(&tlv, 0x03); /* SCR_Card Handle */ sprintf(szTemp, "%ld", pCard->hCard); TLVAddBuffer(&tlv, (u8 *) szTemp, strlen(szTemp)); if (pCard->language != NULL) { TLVNext(&tlv, 0x04); /* SCR_Card language */ TLVAddBuffer(&tlv, (u8 *) pCard->language, strlen(pCard->language)); } if (pCard->id.data != NULL) { TLVNext(&tlv, 0x05); /* SCR_Card id */ TLVAddBuffer(&tlv, pCard->id.data, pCard->id.length); } TLVNext(&tlv, 0x06); /* PinID */ TLVAdd(&tlv, pinID); if (pUsage != NULL) { TLVNext(&tlv, 0x07); /* SCR_PinUsage code */ sprintf(szTemp, "%ld", pUsage->code); TLVAddBuffer(&tlv, (u8 *) szTemp, strlen(szTemp)); if (pUsage->shortString != NULL) { TLVNext(&tlv, 0x08); /* SCR_PinUsage shortstring */ TLVAddBuffer(&tlv, (u8 *) pUsage->shortString, strlen(pUsage->shortString)); } if (pUsage->longString != NULL) { TLVNext(&tlv, 0x09); /* SCR_PinUsage longstring */ TLVAddBuffer(&tlv, (u8 *) pUsage->longString, strlen(pUsage->longString)); } } if (pApp->id.data != NULL) { TLVNext(&tlv, 0x0A); /* SCR_Application id */ TLVAddBuffer(&tlv, (u8 *) pApp->id.data, pApp->id.length); } if (pApp->shortString != NULL) { TLVNext(&tlv, 0x0B); /* SCR_Application shortstring */ TLVAddBuffer(&tlv, (u8 *) pApp->shortString, strlen(pApp->shortString)); } if (pApp->longString != NULL) { TLVNext(&tlv, 0x0C); /* SCR_Application longstring */ TLVAddBuffer(&tlv, (u8 *) pApp->longString, strlen(pApp->longString)); } #ifdef HAVE_PCSC_OLD rv = SCardControl(SCR_CARD_HANDLE, sendbuf, TLVLen(&tlv), recvbuf, &dwRecvLength); #else rv = SCardControl(SCR_CARD_HANDLE, 0, sendbuf, TLVLen(&tlv), recvbuf, dwRecvLength, &dwRecvLength); #endif if (dwRecvLength < 2) { rv = SC_ERROR_UNKNOWN_DATA_RECEIVED; } else { memcpy(pCardStatus, recvbuf, 2); } 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); }
int main(int argc, char *argv[]) { LONG rv; SCARDCONTEXT hContext; SCARDHANDLE hCard; char *reader; BYTE pbSendBuffer[1 + 1 + sizeof(nfc_connstring)]; DWORD dwSendLength; BYTE pbRecvBuffer[1]; DWORD dwActiveProtocol, dwRecvLength, dwReaders; char* mszReaders = NULL; if (argc == 1 || (argc == 2 && (strncmp(argv[1], "yes", strlen("yes")) == 0))) pbSendBuffer[0] = IFDNFC_SET_ACTIVE; else if (argc == 2 && (strncmp(argv[1], "no", strlen("no")) == 0)) pbSendBuffer[0] = IFDNFC_SET_INACTIVE; else if (argc == 2 && (strncmp(argv[1], "se", strlen("se")) == 0)) pbSendBuffer[0] = IFDNFC_SET_ACTIVE_SE; else if (argc == 2 && (strncmp(argv[1], "status", strlen("status")) == 0)) pbSendBuffer[0] = IFDNFC_GET_STATUS; else { printf("Usage: %s [yes|no|status]\n", argv[0]); exit(EXIT_FAILURE); } rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (rv < 0) goto pcsc_error; dwReaders = 0; // Ask how many bytes readers list take rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); if (rv < 0) goto pcsc_error; // Then allocate and fill mszReaders mszReaders = malloc(dwReaders); rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); if (rv < 0) goto pcsc_error; int l; for (reader = mszReaders; dwReaders > 0; l = strlen(reader) + 1, dwReaders -= l, reader += l) { if (strcmp(IFDNFC_READER_NAME, reader) <= 0) break; } if (dwReaders <= 0) { printf("Could not find a reader named: %s\n", IFDNFC_READER_NAME); rv = SCARD_E_NO_READERS_AVAILABLE; goto pcsc_error; } // TODO Handle multiple ifdnfc instance for multiple NFC device ? rv = SCardConnect(hContext, reader, SCARD_SHARE_DIRECT, 0, &hCard, &dwActiveProtocol); if (rv < 0) goto pcsc_error; if ((pbSendBuffer[0] == IFDNFC_SET_ACTIVE) || (pbSendBuffer[0] == IFDNFC_SET_ACTIVE_SE)) { const BYTE command = pbSendBuffer[0]; // To correctly probe NFC devices, ifdnfc must be disactivated first pbSendBuffer[0] = IFDNFC_SET_INACTIVE; dwSendLength = 1; rv = SCardControl(hCard, IFDNFC_CTRL_ACTIVE, pbSendBuffer, dwSendLength, pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength); if (rv < 0) { goto pcsc_error; } pbSendBuffer[0] = command; // Initialize libnfc nfc_context *context; nfc_init(&context); if (context == NULL) { fprintf(stderr, "Unable to init libnfc (malloc)\n"); goto error; } // Allocate nfc_connstring array nfc_connstring connstrings[MAX_DEVICE_COUNT]; // List devices size_t szDeviceFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT); int connstring_index = -1; switch (szDeviceFound) { case 0: fprintf(stderr, "Unable to activate ifdnfc: no NFC device found.\n"); nfc_exit(context); goto error; break; case 1: // Only one NFC device available, so auto-select it! connstring_index = 0; break; default: // More than one available NFC devices, propose a shell menu: printf("%d NFC devices found, please select one:\n", (int)szDeviceFound); for (size_t i = 0; i < szDeviceFound; i++) { nfc_device *pnd = nfc_open(context, connstrings[i]); if (pnd != NULL) { printf("[%d] %s\t (%s)\n", (int)i, nfc_device_get_name(pnd), nfc_device_get_connstring(pnd)); nfc_close(pnd); } else { fprintf(stderr, "nfc_open failed for %s\n", connstrings[i]); } } // libnfc isn't needed anymore nfc_exit(context); printf(">> "); // Take user's choice if (1 != scanf("%2d", &connstring_index)) { fprintf(stderr, "Value must an integer.\n"); goto error; } if ((connstring_index < 0) || (connstring_index >= (int)szDeviceFound)) { fprintf(stderr, "Invalid index selection.\n"); goto error; } break; } printf("Activating ifdnfc with \"%s\"...\n", connstrings[connstring_index]); // pbSendBuffer = { IFDNFC_SET_ACTIVE (1 byte), length (2 bytes), nfc_connstring (lenght bytes)} const uint16_t u16ConnstringLength = strlen(connstrings[connstring_index]) + 1; memcpy(pbSendBuffer + 1, &u16ConnstringLength, sizeof(u16ConnstringLength)); memcpy(pbSendBuffer + 1 + sizeof(u16ConnstringLength), connstrings[connstring_index], u16ConnstringLength); dwSendLength = 1 + sizeof(u16ConnstringLength) + u16ConnstringLength; } else { // pbSendBuffer[0] != IFDNFC_SET_ACTIVE dwSendLength = 1; } rv = SCardControl(hCard, IFDNFC_CTRL_ACTIVE, pbSendBuffer, dwSendLength, pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength); if (rv < 0) { goto pcsc_error; } if (dwRecvLength < 1) { rv = SCARD_F_INTERNAL_ERROR; goto pcsc_error; } switch (pbRecvBuffer[0]) { case IFDNFC_IS_ACTIVE: { uint16_t u16ConnstringLength; if (dwRecvLength < (1 + sizeof(u16ConnstringLength))) { rv = SCARD_F_INTERNAL_ERROR; goto pcsc_error; } memcpy(&u16ConnstringLength, pbRecvBuffer + 1, sizeof(u16ConnstringLength)); if ((dwRecvLength - (1 + sizeof(u16ConnstringLength))) != u16ConnstringLength) { rv = SCARD_F_INTERNAL_ERROR; goto pcsc_error; } nfc_connstring connstring; memcpy(connstring, pbRecvBuffer + 1 + sizeof(u16ConnstringLength), u16ConnstringLength); printf("%s is active using %s.\n", IFDNFC_READER_NAME, connstring); } break; case IFDNFC_IS_INACTIVE: printf("%s is inactive.\n", IFDNFC_READER_NAME); break; default: rv = SCARD_F_INTERNAL_ERROR; goto pcsc_error; } rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD); if (rv < 0) goto pcsc_error; free(mszReaders); exit(EXIT_SUCCESS); pcsc_error: puts(pcsc_stringify_error(rv)); error: if (mszReaders) free(mszReaders); exit(EXIT_FAILURE); }
PaceOutput PCSCReader::establishPACEChannel(const PaceInput &input) const { PaceOutput output; DWORD r, recvlen; uint8_t length_CHAT, length_PIN, PinID; uint16_t lengthInputData, lengthCertificateDescription; BYTE recvbuf[1024]; if (input.get_chat().size() > 0xff || input.get_pin().size() > 0xff) throw PACEException(); length_CHAT = (uint8_t) input.get_chat().size(); length_PIN = (uint8_t) input.get_pin().size(); //FIXME input.get_certificate_description().size(); // The certificate description we get is in wrong format lengthCertificateDescription = 0; lengthInputData = sizeof PinID + sizeof length_CHAT + length_CHAT + sizeof length_PIN + length_PIN + sizeof lengthCertificateDescription + lengthCertificateDescription; size_t sendlen = 1 + 2 + lengthInputData; BYTE *sendbuf = (BYTE *) malloc(sendlen); if (!sendbuf) throw TransactionFailed(); switch (input.get_pin_id()) { case PaceInput::mrz: PinID = PIN_ID_MRZ; break; case PaceInput::pin: PinID = PIN_ID_PIN; break; case PaceInput::can: PinID = PIN_ID_CAN; break; case PaceInput::puk: PinID = PIN_ID_PUK; break; default: PinID = 0; break; } *sendbuf = FUNCTION_EstabishPACEChannel; memcpy(sendbuf + 1, &lengthInputData, sizeof lengthInputData); memcpy(sendbuf + 1 + sizeof lengthInputData, &PinID, sizeof PinID); memcpy(sendbuf + 1 + sizeof lengthInputData + sizeof PinID, &length_CHAT, sizeof length_CHAT); memcpy(sendbuf + 1 + sizeof lengthInputData + sizeof PinID + sizeof length_CHAT, input.get_chat().data(), length_CHAT); memcpy(sendbuf + 1 + sizeof lengthInputData + sizeof PinID + sizeof length_CHAT + length_CHAT, &length_PIN, sizeof length_PIN); memcpy(sendbuf + 1 + sizeof lengthInputData + sizeof PinID + sizeof length_CHAT + length_CHAT + sizeof length_PIN, input.get_pin().data(), length_PIN); memcpy(sendbuf + 1 + sizeof lengthInputData + sizeof PinID + sizeof length_CHAT + length_CHAT + sizeof length_PIN + length_PIN, &lengthCertificateDescription, sizeof lengthCertificateDescription); memcpy(sendbuf + 1 + sizeof lengthInputData + sizeof PinID + sizeof length_CHAT + length_CHAT + sizeof length_PIN + length_PIN + sizeof lengthCertificateDescription, input.get_certificate_description().data(), lengthCertificateDescription); hexdump(DEBUG_LEVEL_CARD, "Execute PACE Input Data (FUNCTION=EstabishPACEChannel)", sendbuf, sendlen); recvlen = sizeof(recvbuf); r = SCardControl(m_hCard, m_ioctl_pace, sendbuf, sendlen, recvbuf, sizeof(recvbuf), &recvlen); hexdump(DEBUG_LEVEL_CARD, "Execute PACE Output Data (FUNCTION=EstabishPACEChannel)", recvbuf, recvlen); free(sendbuf); return parse_EstablishPACEChannel_OutputData(recvbuf, recvlen); }
LC_CLIENT_RESULT LC_Client_ExecApdu(LC_CLIENT *cl, LC_CARD *card, const char *apdu, unsigned int apdulen, GWEN_BUFFER *rbuf, LC_CLIENT_CMDTARGET t) { LONG rv; unsigned char rbuffer[300]; DWORD rblen; assert(cl); assert(card); assert(apdu); assert(apdulen>3); if (t==LC_Client_CmdTargetReader) { int feature; uint32_t controlCode; feature=apdu[0]; controlCode= (apdu[1]<<24)+ (apdu[2]<<16)+ (apdu[3]<<8)+ apdu[4]; if (feature && controlCode==0) controlCode=LC_Card_GetFeatureCode(card, feature); if (controlCode==0) { DBG_ERROR(LC_LOGDOMAIN, "Bad control code for feature %d of reader \"%s\"", feature, LC_Card_GetReaderName(card)); return LC_Client_ResultInvalid; } DBG_DEBUG(LC_LOGDOMAIN, "Sending command to reader (control: %08x):", controlCode); GWEN_Text_LogString((const char*)apdu+5, apdulen-5, LC_LOGDOMAIN, GWEN_LoggerLevel_Debug); rblen=sizeof(rbuffer); rv=SCardControl(LC_Card_GetSCardHandle(card), controlCode, apdu+5, apdulen-5, rbuffer, sizeof(rbuffer), &rblen); if (rv!=SCARD_S_SUCCESS) { DBG_ERROR(LC_LOGDOMAIN, "SCardControl: %04lx", (long unsigned int) rv); return LC_Client_ResultIoError; } if (rblen) { GWEN_Buffer_AppendBytes(rbuf, (const char*)rbuffer, rblen); if (rblen>1) { LC_Card_SetLastResult(card, "ok", "SCardControl succeeded", rbuffer[rblen-2], rbuffer[rblen-1]); } } return LC_Client_ResultOk; } else { SCARD_IO_REQUEST txHeader; SCARD_IO_REQUEST rxHeader; DBG_DEBUG(LC_LOGDOMAIN, "Sending command to card:"); GWEN_Text_LogString((const char*)apdu, apdulen, LC_LOGDOMAIN, GWEN_LoggerLevel_Debug); txHeader.dwProtocol=LC_Card_GetProtocol(card); //txHeader.dwProtocol=1; txHeader.cbPciLength=sizeof(txHeader); rxHeader.cbPciLength=sizeof(rxHeader); rblen=sizeof(rbuffer); rv=SCardTransmit(LC_Card_GetSCardHandle(card), &txHeader, (LPCBYTE) apdu, apdulen, &rxHeader, rbuffer, &rblen); if (rv!=SCARD_S_SUCCESS) { DBG_ERROR(LC_LOGDOMAIN, "SCardControl: %04lx", (long unsigned int) rv); return LC_Client_ResultIoError; } DBG_DEBUG(LC_LOGDOMAIN, "Received response:"); GWEN_Text_LogString((const char*)rbuffer, rblen, LC_LOGDOMAIN, GWEN_LoggerLevel_Debug); if (rblen) { GWEN_Buffer_AppendBytes(rbuf, (const char*)rbuffer, rblen); if (rblen>1) { LC_Card_SetLastResult(card, "ok", "SCardTransmit succeeded", rbuffer[rblen-2], rbuffer[rblen-1]); } } else { DBG_DEBUG(LC_LOGDOMAIN, "Empty response"); } return LC_Client_ResultOk; } }
PCSCReader::PCSCReader( const string &readerName, vector<ICardDetector *>& detector) : IReader(readerName, detector), m_hCard(0x0), #if defined(_WIN32) m_dwProtocol(SCARD_PROTOCOL_UNDEFINED), #else m_dwProtocol(SCARD_PROTOCOL_UNSET), #endif m_hScardContext(0x0) { DWORD retValue = SCARD_S_SUCCESS; BYTE sendbuf[] = { FUNCTION_GetReadersPACECapabilities, 0x00, /* lengthInputData */ 0x00, /* lengthInputData */ }; if ((retValue = SCardEstablishContext(/*SCARD_SCOPE_USER*/ SCARD_SCOPE_SYSTEM, 0x0, 0x0, &m_hScardContext)) != SCARD_S_SUCCESS) eCardCore_warn(DEBUG_LEVEL_CARD, "SCardEstablishContext failed. 0x%08X (%s:%d)", retValue, __FILE__, __LINE__); #if defined(UNICODE) || defined(_UNICODE) WCHAR *_readerName = new WCHAR[m_readerName.size() + 1]; mbstowcs(_readerName, m_readerName.c_str(), m_readerName.size()); _readerName[m_readerName.size()] = 0; retValue = SCardConnect(m_hScardContext, _readerName, SCARD_SHARE_DIRECT, m_dwProtocol, &m_hCard, &m_dwProtocol); delete [] _readerName; #else retValue = SCardConnect(m_hScardContext, m_readerName.c_str(), SCARD_SHARE_DIRECT, m_dwProtocol, &m_hCard, &m_dwProtocol); #endif if (retValue != SCARD_S_SUCCESS) { eCardCore_warn(DEBUG_LEVEL_CARD, "SCardConnect for %s failed. 0x%08X (%s:%d)", m_readerName.c_str(), retValue, __FILE__, __LINE__); } /* does the reader support PACE? */ m_ioctl_pace = 0; #if ENABLE_PACE BYTE recvbuf[1024]; DWORD recvlen = sizeof(recvbuf); retValue = SCardControl(m_hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, recvbuf, sizeof(recvbuf), &recvlen); if (retValue != SCARD_S_SUCCESS) { eCardCore_warn(DEBUG_LEVEL_CARD, "SCardControl for the reader's features failed. 0x%08X (%s:%d)", retValue, __FILE__, __LINE__); } else { for (size_t i = 0; i + PCSC_TLV_ELEMENT_SIZE <= recvlen; i += PCSC_TLV_ELEMENT_SIZE) if (recvbuf[i] == FEATURE_EXECUTE_PACE) memcpy(&m_ioctl_pace, recvbuf + i + 2, 4); } if (0 == m_ioctl_pace) { eCardCore_info(DEBUG_LEVEL_CARD, "Reader does not support PACE"); } else { /* convert to host byte order to use for SCardControl */ m_ioctl_pace = ntohl(m_ioctl_pace); hexdump(DEBUG_LEVEL_CARD, "Execute PACE Input Data (FUNCTION=GetReadersPACECapabilities)", sendbuf, sizeof sendbuf); recvlen = sizeof(recvbuf); retValue = SCardControl(m_hCard, m_ioctl_pace, sendbuf, sizeof sendbuf, recvbuf, sizeof(recvbuf), &recvlen); hexdump(DEBUG_LEVEL_CARD, "Execute PACE Output Data (FUNCTION=GetReadersPACECapabilities)", recvbuf, recvlen); if (retValue == SCARD_S_SUCCESS && recvlen == 7 && recvbuf[0] == 0 && recvbuf[1] == 0 && recvbuf[2] == 0 && recvbuf[3] == 0) { if (recvbuf[6] & BITMAP_Qualified_Signature) eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports qualified signature"); if (recvbuf[6] & BITMAP_German_eID) eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports German eID"); if (recvbuf[6] & BITMAP_PACE) { eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports PACE"); } else m_ioctl_pace = 0; if (recvbuf[6] & BITMAP_DestroyPACEChannel) eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports DestroyPACEChannel"); } else { eCardCore_warn(DEBUG_LEVEL_CARD, "Error executing GetReadersPACECapabilities"); m_ioctl_pace = 0; } } #endif }
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); }