2016-12-05 22 views
4

Я пытаюсь отправить команду на смарт-карту. Я использую Gemalto IDBridge CT30 (PC TWIN reader) и IDBridge K30, подключенные к устройству Android через USB.Общайтесь с считывателем смарт-карт через хост Android USB

Я пытаюсь отправить ВЫБЕРИТЕ команду APDU над USB:

boolean claim = openedConnection.claimInterface(usbInterface, true); 
byte[] data = new byte[]{ 
     (byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x0C, 
     (byte) 0x07, (byte) 0xA0, (byte) 0x00, (byte) 0x00, 
     (byte) 0x01, (byte) 0x18, (byte) 0x45, (byte) 0x4E}; 

После этого я получаю ответ:

final int dataTransferred = this.openedConnection.bulkTransfer(endPointOut, data, data.length, TIMEOUT_MS); 
if(!(dataTransferred == 0 || dataTransferred == data.length)) { 
    throw new Exception("Error durring sending command [" + dataTransferred + " ; " + data.length + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
} 

final byte[] responseBuffer = new byte[endPointIn.getMaxPacketSize()]; 
final int dataTransferred = this.openedConnection.bulkTransfer(this.endPointIn, responseBuffer, responseBuffer.length, TIMEOUT_MS); 
Console.writeLine("USB Retrieve: " + dataTransferred + " " + responseBuffer.length); 
if(dataTransferred >= 0){ 
    return responseBuffer; 
} 
throw new Exception("Error durring receinving response [" + dataTransferred + "]"); 

Этот ответ является

0x00 0x00 0x00 0x00 0x00 0xA0 0x00 0x41 0x03 0x00 

Однако, я должен получить ответ от 0x90 0x00 согласно test project here.

Что я делаю неправильно? Кто-нибудь может мне помочь? Использую ли я правильный подход? Я не использую классы пакетов по умолчанию javax.smartcardio. Я напрямую использую классы интерфейса USB (например, UsbDevice).

ответ

0

То, что вы отправляете, является командой SELECT с заданной AID, которая легко может произвести результат. Вы четко указать, однако, что вы не заинтересованы в ответ на

  • установки Р2 «0C»
  • не обеспечивая байт LE (предполагается, что протокол блок на основе, конечно, разумно для USB)

Таким образом, можно сделать вывод, что ваша карта не соответствует стандарту ISO 7816-4; с другой стороны, ответ не содержит ничего похожего на статус ошибки SW1/SW2, вы уверены, что сброс буфера сброса?

+0

Этот набор байтов (команда) был отправлен в классическом проекте Java по умолчанию (ссылка в главном вопросе) через классы пакета javax.smartcardio и те же самые байты, которые я пытаюсь отправить с помощью интерфейса Android с такими классами, как UsbDevice, но ответ совсем другой. @guidot – user997777

+0

(Остерегайтесь) OP отправляет APDU на конечную точку USB, поэтому ему нужно использовать CCID - см. ответ Майкла Роланда (вы не можете напрямую отправлять APDU здесь) – vlp

7

Ваше устройство чтения говорит CCID через интерфейс USB. Вы не можете просто отправить команду APDU (команда смарт-карты) поверх конечной точки массового вывода и ожидать получения APDU ответа в конечной точке массового ввода. Вместо этого вам необходимо реализовать протокол класса устройства CCID (см. USB Device Class Specifications). Шаги что-то вроде:

  1. Отправить команду PC_to_RDR_IccPowerOn для активации карты.
     
    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. Получите ATR через 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. Отправить команду APDU обернутый в команду PC_to_RDR_XfrBlock
     
    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. Получение APDU ответа через 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. Повторите шаги 3 и 4 для каждого обмена APDU (не забудьте увеличить порядковый номер).

Поскольку ATR указывает, что T = 1 в качестве первого протокола, может потребоваться обернуть APDU в T = 1 TPDU (в зависимости от конфигурации считывателя).I-блок в первый APDU будет выглядеть примерно так:

 
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 

Так что ваша команда PC_to_RDR_XfrBlock будет выглядеть:

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

Вы бы тогда либо получить ответ, завернутый в I-блоке или R- или S-блок, указывающий, что требуется специальная обработка/обработка ошибок.

+0

После отправки IccPowerOn - я получаю: ** 80 18 00 00 00 00 00 00 00 00 3B BF 11 00 81 31 FE 45 45 50 41 00 00 00 00 00 00 00 00 00 00 00 F1 ** и после отправки следующей команды XfrBlock я получаю: ** 00 00 00 00 00 00 01 40 03 00 **. Но я не могу проанализировать результат как ResponseAPDU (потому что он является частью пакета javax.smartcardio), но результатом является массив байтов (как указано выше). Но результат по-прежнему отличается. Я также посылаю команду как массив байтов, а не как класс CommandAPDU. @MichaelRoland – user997777

+1

@ user997777 См. Мой обновленный ответ. Очевидно, что вы не можете использовать классы APDU из Java SmartcardIO, так как это нелегко доступно на складе Android, хотя вы можете реализовать собственный провайдер поверх классов USB и платформы Java SmartcardIO. В любом случае вам нужно говорить CCID, а не APDU через USB. ** Вы обязательно должны прочитать спецификацию CCID. ** –

+0

Спасибо за ваш ответ, но, вероятно, что-то не хватает. Единственные две команды, которые я отправляю, это PC_to_RDR_IccPowerOn, и когда придет правильный ответ с ATR, после этой команды PC_to_RDR_XfrBlock, которая все еще возвращает только 10 байт ** (80 00 00 00 00 00 01 40 F4 00) ** и не ваш ответ APDU. Я уже пробовал много реализаций, которые содержат только эти два шага, и я все равно получаю тот же результат. Возможно ли, что я что-то забыл? Некоторое взаимодействие и так далее? @MichaelRoland – user997777

 Смежные вопросы

  • Нет связанных вопросов^_^