Communicate with smartcard reader through Android USB host

后端 未结 2 1295
一个人的身影
一个人的身影 2020-12-05 08:45

I\'m trying to send a command to a smart card. I use a Gemalto IDBridge CT30 (PC TWIN reader) and a IDBridge K30 connected to the Android device over USB.

I try to s

相关标签:
2条回答
  • 2020-12-05 09:20

    What you send is a SELECT command, with a given AID, which easily could produce a result. You clearly indicate, however, that you are not interested in a response, by

    • setting P2 to '0C'
    • not providing an LE byte (assuming a block based protocol, surely reasonable for USB)

    So one may conclude, that your card is not compliant to ISO 7816-4; on the other hand, the response does not contain anything looking like an error SW1/SW2 status either, are you sure, to have responsebuffer dumped?

    0 讨论(0)
  • 2020-12-05 09:26

    Your reader device speaks CCID over the USB interface. You cannot simply send an APDU (smartcard command) over the bulk-out endpoint and expect to receive a response APDU over the bulk-in endpoint. Instead you need to implement the CCID device class protocol (see USB Device Class Specifications). The steps are something like:

    1. Send PC_to_RDR_IccPowerOn command to activate the card.
      62 00000000 00 00 00 0000 
      |  |        |  |  |  |    |
      |  |        |  |  |  |    \--> Empty data field
      |  |        |  |  |  \-------> Unused, set to 0x0000
      |  |        |  |  \----------> Power select: 0x00 indicates automatic selection
      |  |        |  \-------------> Sequence number (increment for each command)
      |  |        \----------------> Slot number (seems to be zero for your device)
      |  \-------------------------> Length of data field (LSB first)
      \----------------------------> Message type: 0x62 indicates PC_to_RDR_IccPowerOn
      
    2. Receive the ATR through RDR_to_PC_DataBlock.
      80 18000000 00 00 00 00 00 3BBF11008131FE45455041000000000000000000000000F1 
      |  |        |  |  |  |  |  |
      |  |        |  |  |  |  |  \--> Data field: ATR
      |  |        |  |  |  |  \-----> Level parameter
      |  |        |  |  |  \--------> Error register (should be zero on success)
      |  |        |  |  \-----------> Status register (should be zero on success)
      |  |        |  \--------------> Sequence number (matches the sequence number of the command)
      |  |        \-----------------> Slot number (matches the slot number of the command)
      |  \--------------------------> Length of data field (LSB first)
      \-----------------------------> Message type: 0x80 indicates RDR_to_PC_DataBlock
      
    3. Send command APDU wrapped into PC_to_RDR_XfrBlock command
      6F 0C000000 00 01 00 0000 00A4040C07A000000118454E
      |  |        |  |  |  |    |
      |  |        |  |  |  |    \--> Data field: Command APDU
      |  |        |  |  |  \-------> Level parameter (0x0000 for normal length APDUs)
      |  |        |  |  \----------> Block waiting timeout
      |  |        |  \-------------> Sequence number (increment for each command)
      |  |        \----------------> Slot number (seems to be zero for your device)
      |  \-------------------------> Length of data field (LSB first)
      \----------------------------> Message type: 0x6F indicates PC_to_RDR_XfrBlock
      
    4. Receive response APDU through RDR_to_PC_DataBlock.
      80 02000000 00 01 00 00 00 9000 
      |  |        |  |  |  |  |  |
      |  |        |  |  |  |  |  \--> Data field: Response APDU
      |  |        |  |  |  |  \-----> Level parameter
      |  |        |  |  |  \--------> Error register (should be zero on success)
      |  |        |  |  \-----------> Status register (should be zero on success)
      |  |        |  \--------------> Sequence number (matches the sequence number of the command)
      |  |        \-----------------> Slot number (matches the slot number of the command)
      |  \--------------------------> Length of data field (LSB first)
      \-----------------------------> Message type: 0x80 indicates RDR_to_PC_DataBlock
      
    5. Repeat steps 3 and 4 for each APDU exchange (don't forget to increment the sequence number).

    Since the ATR indicates T=1 as first protocol, you might need to wrap your APDU into T=1 TPDUs (depending on the reader configuration). The I-block for the first APDU would look something like:

    00 00 0C 00A4040C07A000000118454E 15
    |  |  |  |                        |
    |  |  |  |                        \--> LRC (due to missing TC in ATR): XOR checksum over all other bytes
    |  |  |  \---------------------------> INF: APDU
    |  |  \------------------------------> LEN: length of INF field
    |  \---------------------------------> PCB: toggle between 0x00 and 0x40 for every other I-block
    \------------------------------------> NAD: node addressing
    

    So your PC_to_RDR_XfrBlock command would look like:

    6F 10000000 00 01 00 0000  00 00 0C 00A4040C07A000000118454E 15
    

    You would then either receive your answer wrapped in an I-block or an R- or S-block indicating that some special/error treatment is necessary.

    0 讨论(0)
提交回复
热议问题