Example #1
0
NTSTATUS
CBTransmit(
          PSMARTCARD_EXTENSION SmartcardExtension
          )
/*++

CBTransmit:
        callback handler for SMCLIB RDF_TRANSMIT

Arguments:
        SmartcardExtension      context of call

Return Value:
        STATUS_SUCCESS
        STATUS_NO_MEDIA
        STATUS_TIMEOUT
        STATUS_INVALID_DEVICE_REQUEST

--*/
{
    NTSTATUS  NTStatus = STATUS_SUCCESS;

    SmartcardDebug(
                  DEBUG_TRACE,
                  ( "PSCR!CBTransmit: Enter\n" )
                  );

        //      dispatch on the selected protocol
    switch ( SmartcardExtension->CardCapabilities.Protocol.Selected ) {
    case SCARD_PROTOCOL_T0:
        NTStatus = CBT0Transmit( SmartcardExtension );
        break;

    case SCARD_PROTOCOL_T1:
        NTStatus = CBT1Transmit( SmartcardExtension );
        break;

    case SCARD_PROTOCOL_RAW:
        NTStatus = CBRawTransmit( SmartcardExtension );
        break;

    default:
        NTStatus = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    SmartcardDebug(
                  DEBUG_TRACE,
                  ( "PSCR!CBTransmit: Exit (%lx)\n", NTStatus )
                  );

    return( NTStatus );
}
Example #2
0
/**
  * @brief  Transmission by T=0 TPDU Mode
  * @param  portno			Indicate which port to open (0:Port0; 1:Port1)
  * @param  pBlockBuffer	Command Data
  * @param  pBlockSize		The size of command data
  * @retval Slot Status Error Code
  */
unsigned char Ifd_XfrTpduT0(int32_t portno,
									unsigned char *pBlockBuffer,
									unsigned int *pBlockSize	)
{
	int32_t ErrorCode;
	uint8_t rbuf[MIN_BUFFER_SIZE];
	uint32_t idx, AnswerSize, rlen;
	S_SC_DEV_T *dev;	
	dev =  (S_SC_DEV_T *)((uint32_t)&sc_device[portno]);

	if( *pBlockBuffer == 0xFF )		/* PPS Exchange Process */
	{
		AnswerSize = 4;
		ErrorCode = CBRawTransmit( dev, pBlockBuffer, *pBlockSize, AnswerSize, &rbuf[0], &rlen);
		if(ErrorCode != SC_STATUS_SUCCESS)
			return Ifd_SC2CCIDErrorCode(ErrorCode);
		
		// received data
		for(idx=0; idx<rlen; idx++) 
		{
			*pBlockBuffer = rbuf[idx];
			pBlockBuffer++;
		}
		// length of received data
		*pBlockSize = rlen;
	}
	else
	{		
		ErrorCode = CBT0Transmit( dev, pBlockBuffer, *pBlockSize, &rbuf[0], &rlen);
		if(ErrorCode != SC_STATUS_SUCCESS)
			return Ifd_SC2CCIDErrorCode(ErrorCode);
		
		// received data
		for(idx=0; idx<rlen; idx++) 
		{
			*pBlockBuffer = rbuf[idx];
			pBlockBuffer++;
		}
		// length of received data
		*pBlockSize = rlen;
	}

	return SLOT_NO_ERROR;

}
Example #3
0
NTSTATUS
CBRawTransmit(
             PSMARTCARD_EXTENSION SmartcardExtension
             )
/*++

CBRawTransmit:
        finishes the callback RDF_TRANSMIT for the RAW protocol

Arguments:
        SmartcardExtension      context of call

Return Value:
        STATUS_SUCCESS
        STATUS_NO_MEDIA
        STATUS_TIMEOUT
        STATUS_INVALID_DEVICE_REQUEST

--*/
{
    NTSTATUS                    NTStatus = STATUS_SUCCESS;
    UCHAR                           TLVList[ TLV_BUFFER_SIZE ],
    Val,
    Len;
    ULONG                           TLVListLen;
    PREADER_EXTENSION       ReaderExtension;

    SmartcardDebug(
                  DEBUG_TRACE,
                  ( "PSCR!CBRawTransmit: Enter\n" )
                  );

    ReaderExtension = SmartcardExtension->ReaderExtension;
        //
        //      read the status file of ICC1 from the reader
        //
    TLVListLen = TLV_BUFFER_SIZE;
    NTStatus = CmdReadStatusFile(
                                ReaderExtension,
                                ReaderExtension->Device,
                                TLVList,
                                &TLVListLen
                                );

        //
        //      check the active protocol of the reader
        //
    if ( NT_SUCCESS( NTStatus )) {
        Len = sizeof(Val);
        NTStatus = CmdGetTagValue(
                                 TAG_ICC_PROTOCOLS,
                                 TLVList,
                                 TLVListLen,
                                 &Len,
                                 ( PVOID ) &Val
                                 );

                //      execute the active protocol
        if ( NT_SUCCESS( NTStatus )) {

                        //      translate the actual protocol to a value the lib can understand
            switch ( Val ) {
            case PSCR_PROTOCOL_T0:
                NTStatus = CBT0Transmit( SmartcardExtension );
                break;
            case PSCR_PROTOCOL_T1:
                NTStatus = CBT1Transmit( SmartcardExtension );
                break;
            default:
                NTStatus = STATUS_UNSUCCESSFUL;
                break;
            }
        }
    }
    SmartcardDebug(
                  DEBUG_TRACE,
                  ( "PSCR!CBRawTransmit: Exit (%lx)\n", NTStatus )
                  );
    return( NTStatus );
}
Example #4
0
/**
  * @brief  Transmission by T=0 Extend APDU Mode
  * @param  portno			Indicate which port to open (0:Port0; 1:Port1)
  * @param  pBlockBuffer	Command Data
  * @param  pBlockSize		The size of command data
  * @retval Slot Status Error Code
  */
unsigned char Ifd_XfrExtendApduT0(	int32_t portno,
												unsigned char *pBlockBuffer,
												unsigned int *pBlockSize	)
{
	int32_t ErrorCode, idx;
	uint8_t rbuf[MIN_BUFFER_SIZE];
	uint32_t datalength, rlen;
	S_SC_DEV_T *dev;
	unsigned char getresponsebuf[5];
	unsigned char envelopebuf[300];	// 255 bytes + 5 command data
	dev =  (S_SC_DEV_T *)((uint32_t)&sc_device[portno]);


	if( UsbMessageBuffer[OFFSET_WLEVELPARAMETER] == 0x01)
	{
		datalength = (*pBlockSize) - 7;
		pBlockBuffer = pBlockBuffer + 7;

		while(datalength)
		{
			envelopebuf[0] = USB_ConfigDescriptor[49+18];		// CLA = bClassEnvelope field
			envelopebuf[1] = 0xC2;							// 0xC2 = Envelope command
			envelopebuf[2] = 0x00;							// 0x00
			envelopebuf[3] = 0x00;							// 0x00
			if(datalength >= 0xFF)
				envelopebuf[4] = 0xFF;						// APDU length > buffer length
			else
				envelopebuf[4] = datalength;					// APDU length > buffer length

			if(datalength >= 0xFF) {
				for(idx=0; idx < 0xFF; idx++)
					envelopebuf[idx + 5] = pBlockBuffer[idx];
			} else {
				for(idx=0; idx < datalength; idx++)
					envelopebuf[idx + 5] = pBlockBuffer[idx];
			}

			if(datalength >= 0xFF)
				ErrorCode = CBT0Transmit( dev, &envelopebuf[0], 0x5+0xFF, &rbuf[0], &rlen);
			else
				ErrorCode = CBT0Transmit( dev, &envelopebuf[0], 0x5+datalength, &rbuf[0], &rlen);
			if(ErrorCode != SC_STATUS_SUCCESS)
				return Ifd_SC2CCIDErrorCode(ErrorCode);

			if(datalength >= 0xFF) {
				pBlockBuffer+=0xFF;
				datalength-=0xFF;
			} else
				datalength-=datalength;

		}
		
		// length of received data
		*pBlockSize = 0;

		// Chain Parameter Setting
		g_ChainParameter = 0x10;
	}
	
	else if( UsbMessageBuffer[OFFSET_WLEVELPARAMETER] == 0x02)
	{
		datalength = (*pBlockSize) - 7;
		pBlockBuffer = pBlockBuffer + 7;
		
		envelopebuf[0] = USB_ConfigDescriptor[49+18];		// CLA = bClassEnvelope field
		envelopebuf[1] = 0xC2;							// 0xC2 = Envelope command
		envelopebuf[2] = 0x00;							// 0x00
		envelopebuf[3] = 0x00;							// 0x00
		envelopebuf[4] = datalength;						// last part of APDU command
		for(idx=0; idx < datalength; idx++)
			envelopebuf[idx + 5] = pBlockBuffer[idx];
		
		ErrorCode = CBT0Transmit( dev, &envelopebuf[0], 0x5+envelopebuf[4], &rbuf[0], &rlen);
		if(ErrorCode != SC_STATUS_SUCCESS)
			return Ifd_SC2CCIDErrorCode(ErrorCode);

		// get response command
		getresponsebuf[0] = USB_ConfigDescriptor[48+18];	// CLA = bClassGetResponse field
		getresponsebuf[1] = 0xC0;							// 0xC0 = Get response command
		getresponsebuf[2] = 0x00;							// 0x00
		getresponsebuf[3] = 0x00;							// 0x00
		getresponsebuf[4] = 0x00;							// 0x00
		
		ErrorCode = CBT0Transmit( dev, &getresponsebuf[0], 0x5, &rbuf[0], &rlen);
		if(ErrorCode != SC_STATUS_SUCCESS)
			return Ifd_SC2CCIDErrorCode(ErrorCode);
		// check if data bytes still available, max. size of buffer is 500 bytes
		//while(1)
		//{
			if((rlen==2) && (rbuf[0]==0x61))
			{
				getresponsebuf[0] = USB_ConfigDescriptor[48+18];	// CLA = bClassGetResponse field
				getresponsebuf[1] = 0xC0;							// 0xC0 == Get response command
				getresponsebuf[2] = 0x00;							// 0x00
				getresponsebuf[3] = 0x00;							// 0x00
				getresponsebuf[4] = rbuf[1];			// Licc = how many data bytes still available
				if(getresponsebuf[4]==0xFF) // TODO: care this point. NOT sure how to handle this
					ErrorCode = CBRawTransmit( dev, &getresponsebuf[0], 0x5, 0xFF, &rbuf[0], &rlen);
				else {
					ErrorCode = CBT0Transmit( dev, &getresponsebuf[0], 0x5, &rbuf[0], &rlen);
					printf("why available data is less than 0xff \n");
				}
				if(ErrorCode != SC_STATUS_SUCCESS)
					return Ifd_SC2CCIDErrorCode(ErrorCode);
			}
			
		//}

		// store received data
		pBlockBuffer = pBlockBuffer - 7;
		for(idx=0; idx<rlen; idx++)
			pBlockBuffer[idx] = rbuf[idx];
		
		// length of received data
		*pBlockSize = getresponsebuf[4];

		// Chain Parameter Setting
		g_ChainParameter = 0x01;
	}
	
	else if( UsbMessageBuffer[OFFSET_WLEVELPARAMETER] == 0x03)
	{
		datalength = (*pBlockSize) - 7;
		pBlockBuffer = pBlockBuffer + 7;

		while(datalength)
		{
			envelopebuf[0] = USB_ConfigDescriptor[49+18];		// CLA = bClassEnvelope field
			envelopebuf[1] = 0xC2;							// 0xC2 = Envelope command
			envelopebuf[2] = 0x00;							// 0x00
			envelopebuf[3] = 0x00;							// 0x00
			if(datalength >= 0xFF)
				envelopebuf[4] = 0xFF;						// APDU length > buffer length
			else
				envelopebuf[4] = datalength;					// APDU length > buffer length

			if(datalength >= 0xFF) {
				for(idx=0; idx < 0xFF; idx++)
					envelopebuf[idx + 5] = pBlockBuffer[idx];
			} else {
				for(idx=0; idx < datalength; idx++)
					envelopebuf[idx + 5] = pBlockBuffer[idx];
			}

			if(datalength >= 0xFF)
				ErrorCode = CBT0Transmit( dev, &envelopebuf[0], 0x5+0xFF, &rbuf[0], &rlen);
			else
				ErrorCode = CBT0Transmit( dev, &envelopebuf[0], 0x5+datalength, &rbuf[0], &rlen);
			if(ErrorCode != SC_STATUS_SUCCESS)
				return Ifd_SC2CCIDErrorCode(ErrorCode);

			if(datalength >= 0xFF) {
				pBlockBuffer+=0xFF;
				datalength-=0xFF;
			} else
				datalength-=datalength;

		}
		
		// length of received data
		*pBlockSize = 0;

		// Chain Parameter Setting
		g_ChainParameter = 0x10;
	}

	else if( UsbMessageBuffer[OFFSET_WLEVELPARAMETER] == 0x10)
	{
		// get response command
		getresponsebuf[0] = USB_ConfigDescriptor[48+18];	// CLA = bClassGetResponse field
		getresponsebuf[1] = 0xC0;							// 0xC0 = Get response command
		getresponsebuf[2] = 0x00;							// 0x00
		getresponsebuf[3] = 0x00;							// 0x00
		getresponsebuf[4] = 0x00;							// 0x00
		
		ErrorCode = CBT0Transmit( dev, &getresponsebuf[0], 0x5, &rbuf[0], &rlen);
		if(ErrorCode != SC_STATUS_SUCCESS)
			return Ifd_SC2CCIDErrorCode(ErrorCode);
		// check if data bytes still available, max. size of buffer is 500 bytes
		if((rlen==2) && (rbuf[0]==0x61))
		{
			getresponsebuf[0] = USB_ConfigDescriptor[48+18];	// CLA = bClassGetResponse field
			getresponsebuf[1] = 0xC0;							// 0xC0 == Get response command
			getresponsebuf[2] = 0x00;							// 0x00
			getresponsebuf[3] = 0x00;							// 0x00
			getresponsebuf[4] = rbuf[1];			// Licc = how many data bytes still available
			if(getresponsebuf[4]==0xFF)
				ErrorCode = CBRawTransmit( dev, &getresponsebuf[0], 0x5, 0xFF, &rbuf[0], &rlen);
			else
				ErrorCode = CBT0Transmit( dev, &getresponsebuf[0], 0x5, &rbuf[0], &rlen);
			if(ErrorCode != SC_STATUS_SUCCESS)
				return Ifd_SC2CCIDErrorCode(ErrorCode);
		}		

		// store received data
		for(idx=0; idx<rlen; idx++)
			pBlockBuffer[idx] = rbuf[idx];
		
		// length of received data
		if(getresponsebuf[4]==0xFF)
			*pBlockSize = getresponsebuf[4];
		else
			*pBlockSize = rlen;

		// Chain Parameter Setting
		if(getresponsebuf[4]==0xFF)
			g_ChainParameter = 0x03;
		else
			g_ChainParameter = 0x02;
	}

	return SLOT_NO_ERROR;

}
Example #5
0
/**
  * @brief  Transmission by T=0 Short APDU Mode
  * @param  portno			Indicate which port to open (0:Port0; 1:Port1)
  * @param  pBlockBuffer	Command Data
  * @param  pBlockSize		The size of command data
  * @retval Slot Status Error Code
  */
unsigned char Ifd_XfrShortApduT0(	int32_t portno,
											unsigned char *pBlockBuffer,
											unsigned int *pBlockSize	)
{
	//uint8_t case_no=0x00;
	int32_t ErrorCode;
	uint8_t rbuf[MIN_BUFFER_SIZE];
	uint8_t rbufICC[MIN_BUFFER_SIZE];
	uint8_t *buf = rbuf;
	uint32_t idx, rlen, rlenICC;
	S_SC_DEV_T *dev;	
	unsigned char blockbuf[5];	
	dev =  (S_SC_DEV_T *)((uint32_t)&sc_device[portno]);

	//case_no = Ifd_CheckCmdCase(pBlockBuffer, *pBlockSize);

	CCIDSCDEBUG("Ifd_XfrShortApduT0: header=%02x %02x %02x %02x, len=%d\n",
		pBlockBuffer[0], pBlockBuffer[1], pBlockBuffer[2], pBlockBuffer[3], *pBlockSize);

	if( *pBlockSize == 0x4 )
	{
		blockbuf[0] = pBlockBuffer[0];
		blockbuf[1] = pBlockBuffer[1];
		blockbuf[2] = pBlockBuffer[2];
		blockbuf[3] = pBlockBuffer[3];
		blockbuf[4] = 0x00;
		
		ErrorCode = CBT0Transmit( dev, &blockbuf[0], 0x5, &rbuf[0], &rlen);
		if(ErrorCode != SC_STATUS_SUCCESS)
			return Ifd_SC2CCIDErrorCode(ErrorCode);
		
		// received data
		for(idx=0; idx<rlen; idx++) 
		{
			*pBlockBuffer = rbuf[idx];
			pBlockBuffer++;
		}
		// length of received data
		*pBlockSize = rlen;
	}
	else 
	{
		ErrorCode = CBT0Transmit( dev, pBlockBuffer, *pBlockSize, &rbuf[0], &rlen);
		if(ErrorCode != SC_STATUS_SUCCESS)
			return Ifd_SC2CCIDErrorCode(ErrorCode);
		
		// check if wrong Le field error
		while((rlen==2) && (rbuf[0]==0x6C))
		{
			pBlockBuffer[4] = rbuf[1];
			ErrorCode = CBT0Transmit( dev, pBlockBuffer, *pBlockSize, &rbuf[0], &rlen);
			if(ErrorCode != SC_STATUS_SUCCESS)
				return Ifd_SC2CCIDErrorCode(ErrorCode);
		}

		// check if data bytes still available
		if((rlen==2) && (rbuf[0]==0x61))
		{
			rlenICC = 0;
			while(1)
			{
				blockbuf[0] = USB_ConfigDescriptor[48+18];	// CLA = bClassGetResponse field
				blockbuf[1] = 0xC0;						// 0xC0 == Get response command
				blockbuf[2] = 0x00;						// 0x00
				blockbuf[3] = 0x00;						// 0x00
				blockbuf[4] = rbuf[rlen-1];			// Licc = how many data bytes still available
				ErrorCode = CBT0Transmit( dev, blockbuf, 0x5, &rbuf[0], &rlen);
				if(ErrorCode != SC_STATUS_SUCCESS)
					return Ifd_SC2CCIDErrorCode(ErrorCode);
				// received data
				if(rbuf[rlen-2]==0x61)
				{
					for(idx=0; idx<rlen-2; idx++) 
						rbufICC[rlenICC++] = rbuf[idx];
				} 
				else
				{
					for(idx=0; idx<rlen; idx++) 
						rbufICC[rlenICC++] = rbuf[idx];
				}
					
				if(rbuf[rlen-2] != 0x61) break;
			}
			rlen = rlenICC;
			buf = rbufICC;
		}
	

		CCIDSCDEBUG("Ifd_XfrShortApduT0: dwLength = %d, Data = ", rlen);

		/* Check status bytes */
		if((buf[rlen-2]&0xF0)!=0x60 && (buf[rlen-2]&0xF0)!=0x90)
			return SLOTERR_ICC_PROTOCOL_NOT_SUPPORTED;

		// received data
		for(idx=0; idx<rlen; idx++) 
		{
			CCIDSCDEBUG("%02x", buf[idx]);
			*pBlockBuffer = buf[idx];
			pBlockBuffer++;
		}
		CCIDSCDEBUG("\n");
			
		// length of received data
		*pBlockSize = rlen;
	}

	return SLOT_NO_ERROR;

}