/*! * \brief Function performs data transmissions T=0.<br> * <br> * \param [in] pSmartcardExtension A pointer to the smart card extension, SMARTCARD_EXTENSION, of the device. * * \retval STATUS_SUCCESS the routine successfully end. */ static NTSTATUS transmitT0(IN PSMARTCARD_EXTENSION pSmartcardExtension) { dbg_log("transmitT0 start"); NTSTATUS status = STATUS_SUCCESS; status = SmartcardT0Request(pSmartcardExtension); if (status != STATUS_SUCCESS) { dbg_log("SmartcardT0Request failed! - status: 0x%08X", status); return status; } dbg_log("transmitT0 SEND: "); dbg_ba2s( (char const *const)pSmartcardExtension->SmartcardRequest.Buffer, pSmartcardExtension->SmartcardRequest.BufferLength ); // send command to JCOP simulator. PREADER_EXTENSION pReaderExtension = pSmartcardExtension->ReaderExtension; // send "APDU" meessage. unsigned char mty = 0x01; // MTY 0x01(APDU) unsigned char nad = 0x00; // NAD status = sendMessage( pReaderExtension, mty, nad, (char *)pSmartcardExtension->SmartcardRequest.Buffer, (unsigned short)pSmartcardExtension->SmartcardRequest.BufferLength, (char *)pSmartcardExtension->SmartcardReply.Buffer, (unsigned short)pSmartcardExtension->SmartcardReply.BufferSize, (unsigned short *) & pSmartcardExtension->SmartcardReply.BufferLength, NULL // wait indefinitely ); dbg_log( "pSmartcardExtension->SmartcardReply.BufferLength: %d", pSmartcardExtension->SmartcardReply.BufferLength ); dbg_ba2s( (char *const)pSmartcardExtension->SmartcardReply.Buffer, pSmartcardExtension->SmartcardReply.BufferLength ); if (status != STATUS_SUCCESS) { dbg_log("sendApduMessage failed! - status: 0x%08X", status); return status; } status = SmartcardT0Reply(pSmartcardExtension); if (status != STATUS_SUCCESS) { dbg_log("SmartcardT0Reply failed! - status: 0x%08X", status); return status; } dbg_log("transmitT0 end - status: 0x%08X", status); return status; }
NTSTATUS CBT0Transmit( PSMARTCARD_EXTENSION SmartcardExtension ) /*++ CBT0Transmit: finishes the callback RDF_TRANSMIT for the T0 protocol Arguments: SmartcardExtension context of call Return Value: STATUS_SUCCESS STATUS_NO_MEDIA STATUS_TIMEOUT STATUS_INVALID_DEVICE_REQUEST --*/ { NTSTATUS NTStatus = STATUS_SUCCESS; PUCHAR pRequest,pReply; ULONG IOBytes, APDULength, RequestLength; UCHAR IOData[ MAX_T1_BLOCK_SIZE ]; UCHAR WtxReply[16]; SmartcardDebug( DEBUG_TRACE, ( "PSCR!CBT0Transmit: Enter\n" ) ); SysFillMemory( SmartcardExtension->SmartcardReply.Buffer, 0xCC, MAX_T1_BLOCK_SIZE ); pRequest = SmartcardExtension->SmartcardRequest.Buffer; pReply = SmartcardExtension->SmartcardReply.Buffer; // setup the command header pRequest[ PSCR_NAD ] = ( SmartcardExtension->ReaderExtension->Device == DEVICE_ICC1 ) ? NAD_TO_ICC1 : NAD_TO_ICC1; pRequest[ PSCR_PCB ] = PCB_DEFAULT; // // get the length of the user data packet & set the appropriate LEN // information the complete user packet consists of a SCARD_IO_REQUEST // structure followed by the APDU. the length of SCARD_IO_REQUEST is // transferred in the member cbPciLength of the structure // APDULength = SmartcardExtension->IoRequest.RequestBufferLength; if ((((PSCARD_IO_REQUEST) SmartcardExtension->IoRequest.RequestBuffer)->cbPciLength) >= APDULength) { // Prevent integer underflow return (STATUS_INSUFFICIENT_RESOURCES); } APDULength -= ((PSCARD_IO_REQUEST) SmartcardExtension-> IoRequest.RequestBuffer)->cbPciLength; // // a 4 byte APDU will be patched to a 5 byte TPDU by the lib; see // annex of the ISO // if ( APDULength == 4 ) APDULength++; // // if the total length of the T1 (reader) packet is larger than 0xFF // the extended length notation will be used // if ( APDULength >= 0xFF ) { pRequest[ PSCR_LEN ] = 0xFF; pRequest[ PSCR_LEN+1 ] = HIBYTE( APDULength ); pRequest[ PSCR_LEN+2 ] = LOBYTE( APDULength ); SmartcardExtension->SmartcardRequest.BufferLength = PSCR_EXT_PROLOGUE_LENGTH; } else { pRequest[ PSCR_LEN ] = ( UCHAR ) APDULength; SmartcardExtension->SmartcardRequest.BufferLength = PSCR_PROLOGUE_LENGTH; } // let the lib setup the T=1 APDU & check for errors NTStatus = SmartcardT0Request( SmartcardExtension ); RequestLength = SmartcardExtension->SmartcardRequest.BufferLength; while ( NT_SUCCESS( NTStatus )) { // check to see if device is busy. { PPSCR_REGISTERS IOBase; UCHAR Status; IOBase = SmartcardExtension->ReaderExtension->IOBase; Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg ); if( 0x03 == Status ) { NTStatus = STATUS_DEVICE_BUSY; break; } } // send command IOBytes = 0; NTStatus = PscrWrite( SmartcardExtension->ReaderExtension, pRequest, RequestLength, &IOBytes ); // get response if ( NT_SUCCESS( NTStatus )) { IOBytes = 0; NTStatus = PscrRead( SmartcardExtension->ReaderExtension, IOData, MAX_T1_BLOCK_SIZE, &IOBytes ); // extract APDU from T=1 transport packet if ( NT_SUCCESS( NTStatus )) { if (IOBytes < 4) { NTStatus = STATUS_DEVICE_PROTOCOL_ERROR; break; } if (IOData[ PSCR_PCB ] == WTX_REQUEST) { WtxReply[PSCR_NAD] = NAD_TO_PSCR; WtxReply[PSCR_PCB] = WTX_REPLY; WtxReply[PSCR_LEN] = 1; WtxReply[PSCR_INF] = IOData[PSCR_INF]; RequestLength = 4; pRequest = WtxReply; continue; } if ( IOData[ PSCR_LEN ] == 0xFF ) { // // extended length byte used // APDULength = IOData[ PSCR_LEN + 1 ] << 8; APDULength += IOData[ PSCR_LEN + 2 ]; SmartcardExtension->SmartcardReply.BufferLength = APDULength ; if (APDULength >= (sizeof(IOData) - (PSCR_APDU + 2))) { NTStatus = STATUS_BUFFER_TOO_SMALL; break; } SysCopyMemory( pReply, &IOData[ PSCR_APDU + 2 ], APDULength ); } else { if ((IOData[PSCR_LEN] > SmartcardExtension->SmartcardReply.BufferSize) || (IOData[PSCR_LEN] > MAX_T1_BLOCK_SIZE + PSCR_APDU)) { NTStatus = STATUS_DEVICE_PROTOCOL_ERROR; break; } SmartcardExtension->SmartcardReply.BufferLength = IOData[ PSCR_LEN ]; SysCopyMemory( pReply, &IOData[ PSCR_APDU ], IOData[ PSCR_LEN ] ); } if( SmartcardExtension->ReaderCapabilities.CurrentState <= SCARD_ABSENT ) { NTStatus = STATUS_NO_MEDIA; } else { // let the lib evaluate the result & tansfer the data NTStatus = SmartcardT0Reply( SmartcardExtension ); } break; } } } // start freeze routine, if an interrupt was sent, but no freeze data was read if( SmartcardExtension->ReaderExtension->RequestInterrupt ) PscrFreeze( SmartcardExtension ); SmartcardDebug( DEBUG_TRACE, ( "PSCR!CBT0Transmit: Exit (%lx)\n", NTStatus ) ); return( NTStatus ); }