Связь с устройством чтения смарт-карт через Android USB-хост

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

Я пытаюсь отправить команду SELECT 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 в соответствии с тестовым проектом здесь.

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

2 ответа

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

  1. Отправьте команду PC_to_RDR_IccPowerOn, чтобы активировать карту.
    62 00000000 00 00 00 0000 
    | | | | | | |
    | | | | | | \ -> Пустое поле данных
    | | | | | \ -------> Не используется, установлено 0x0000
    |  |        |  |  \----------> Power select: 0x00 обозначает автоматический выбор
    | | | \ -------------> Порядковый номер (приращение для каждой команды)
    |  |        \----------------> Номер слота (кажется, ноль для вашего устройства)
    |  \-------------------------> Длина поля данных (сначала LSB)
    \----------------------------> Тип сообщения: 0x62 указывает PC_to_RDR_IccPowerOn
  2. Получите ATR через RDR_to_PC_DataBlock.
    80 18000000 00 00 00 00 00 3BBF11008131FE45455041000000000000000000000000F1 
    | | | | | | | |
    | | | | | | | \ -> Поле данных: ATR
    |  |        |  |  |  |  \-----> параметр уровня
    | | | | | \ --------> Регистр ошибок (должен быть равен нулю в случае успеха)
    |  |        |  |  \-----------> Регистр статуса (должен быть равен нулю в случае успеха)
    |  |        |  \--------------> Порядковый номер (соответствует порядковому номеру команды)
    |  |        \-----------------> Номер слота (соответствует номеру слота команды)
    |  \--------------------------> Длина поля данных (сначала LSB)
    \-----------------------------> Тип сообщения: 0x80 обозначает RDR_to_PC_DataBlock
  3. Отправить команду APDU, завернутую в команду PC_to_RDR_XfrBlock
    6F 0C000000 00 01 00 0000 00A4040C07A000000118454E
    |  |        |  |  |  |    |
    |  |        |  |  |  |    \-> Поле данных: Команда APDU
    |  |        |  |  |  \-------> Параметр уровня (0x0000 для APDU нормальной длины)
    |  |        |  |  \----------> Заблокировать время ожидания
    | | | \ -------------> Порядковый номер (приращение для каждой команды)
    |  |        \----------------> Номер слота (кажется, ноль для вашего устройства)
    |  \-------------------------> Длина поля данных (сначала LSB)
    \----------------------------> Тип сообщения: 0x6F указывает PC_to_RDR_XfrBlock
  4. Получите ответ APDU через RDR_to_PC_DataBlock.
    80 02000000 00 01 00 00 00 9000 
    | | | | | | | |
    | | | | | | | \ -> Поле данных: Ответ APDU
    |  |        |  |  |  |  \-----> параметр уровня
    | | | | | \ --------> Регистр ошибок (должен быть равен нулю в случае успеха)
    |  |        |  |  \-----------> Регистр статуса (должен быть равен нулю в случае успеха)
    |  |        |  \--------------> Порядковый номер (соответствует порядковому номеру команды)
    |  |        \-----------------> Номер слота (соответствует номеру слота команды)
    |  \--------------------------> Длина поля данных (сначала LSB)
    \-----------------------------> Тип сообщения: 0x80 обозначает RDR_to_PC_DataBlock
  5. Повторите шаги 3 и 4 для каждого обмена APDU (не забудьте увеличить порядковый номер).

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

00 00 0C 00A4040C07A000000118454E 15
| | | | |
| | | | \ -> LRC (из-за отсутствия TC в ATR): контрольная сумма XOR для всех остальных байтов
|  |  |  \---------------------------> INF: APDU
|  |  \------------------------------> LEN: длина поля INF
|  \---------------------------------> PCB: переключение между 0x00 и 0x40 для каждого другого I-блока
\------------------------------------> NAD: адресация узлов

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

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

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

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

  • установка P2 на "0C"
  • не обеспечивает LE байт (предполагается, что протокол на основе блоков, безусловно, целесообразно для USB)

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

Другие вопросы по тегам