Управляйте полным APDU с помощью эмуляции программной карты NFC на Android

Я занят приложением для эмуляции обычной связи APDU на Nexus 7 с CM10.1 с устройством чтения/записи ACR122U102. Я нашел этот блог о программной эмуляции карты и написал приложение, чтобы мое устройство (нексус) отображалось как карточка. Теперь я пытаюсь отправлять сообщения туда и обратно между этим устройством и ACR122u. До сих пор мне удалось связаться только с Nexus 7, отправив D4 40 01 (InDataExchange стр. 127) APDU. Для приложения, которое я пишу, этого должно быть достаточно.

Проблема заключается в ответе, который я посылаю с устройства на ридер. Используя функцию передачи (android.nfc. tech.IsoPcdA с отражением), я могу ответить массивом байтов длины > 0. Это будет отображаться на стороне читателя как обычный ответ InDataExchange (например: D5 41 00 01 02 03 с {01 02 03} — это массив байтов, предоставленный функции приема). Но я не могу контролировать ни байт состояния, ни байты SW в ответе (D5 41 XX и оба SW). Документации по этому классу IsoPcdA нет, кроме самого исходного кода.

Что я хочу сделать, так это изменить XX на байт по моему выбору и отправить ответы длины = 0 (например: D5 41 01 без каких-либо дополнительных данных). Является ли это возможным?


person Fons    schedule 27.05.2013    source источник


Ответы (1)


Я не совсем уверен, чего вы пытаетесь достичь здесь. Что бы вы ни передавали с помощью метода передачи IsoPcdA, это полные APDU (как определено в ISO/IEC 7816-4, или, скорее, любой PDU в транспортном протоколе ISO-DEP). Таким образом, возвращаемое значение команды «передача» представляет собой полный C-APDU (командный APDU), а параметр массива байтов функции «передача» представляет собой полный R-APDU (ответный APDU), включая два байта слова состояния (SW1 | SW2). Таким образом, последние два байта этого параметра являются словом состояния. В вашем примере SW1 будет 02, а SW2 будет 03.

То, что вы видите как байт состояния в команде InDataExchange контроллера PN532 NFC, — это не слово состояния APDU, а статус выполнения команды в контроллере PN532 NFC. Этот байт состояния дает вам информацию о переполнении буфера, тайм-аутах связи и т. д. и не является чем-то, что возвращается стороной карты.

EDIT: пример кода + тестовые команды:

Пример кода, работающего на Galaxy Nexus (CM 10):

try {
  Class isoPcdA = Class.forName("android.nfc.tech.IsoPcdA");
  Method isoPcdA_get = isoPcdA.getDeclaredMethod("get", Tag.class);

  final IsoPcdA techIsoPcdA = (IsoPcdA)isoPcdA_get.invoke(null, tag);

  if (techIsoPcdA != null) {
    if (mWorker != null) {
      mInterrupt = true;
      mWorker.interrupt();
      try {
        mWorker.join();
      } catch (Exception e) {}
    }

    mInterrupt = false;
    mWorker = new Thread(new Runnable() {
      public void run () {
        try {
          techIsoPcdA.connect();

          byte[] command = techIsoPcdA.transceive(new byte[]{ (byte)0x90, (byte)0x00 });
          Log.d(CardEmulationTest.class.getName(), "Connected.");

          while (!mInterrupt) {
            Log.d(CardEmulationTest.class.getName(), "C-APDU=" + StringUtils.convertByteArrayToHexString(command));
            command = techIsoPcdA.transceive(command);
          }
        } catch (Exception e) {
          Log.e(CardEmulationTest.class.getName(), "Exception while communicating on IsoPcdA object", e);
        } finally {
          try {
            techIsoPcdA.close();
          } catch (Exception e) {}
        }
      }
    });

    mWorker.start();
  }
} catch (Exception e) {
  Log.e(CardEmulationTest.class.getName(), "Exception while processing IsoPcdA object", e);
}

Тест (с использованием ACR122U):

InListPassivTargets (1 цель на скорости 106 кбит/с)

> FF00000004 D44A 0100 00
< D54B 010100046004088821310578338800 9000

InDataExchange с ДАННЫМИ = 0x01

> FF00000004 D440 01 01 00
< D541 00 01 9000

Таким образом, мы получаем код ошибки 0x00 от устройства чтения карт (состояние команды InDataExchange; не является частью фактического APDU ответа), мы получаем 0x01 в качестве ответа (это APDU ответа IsoDepA) и мы получаем 0x9000 в качестве кода состояния для APDU оболочки считывателя карт (не являющийся частью фактического ответного APDU).

InDataExchange с ДАННЫМИ = 0x01 0x02

> FF00000005 D440 01 0102 00
< D541 00 0102 9000

Таким образом, мы получаем код ошибки 0x00 от устройства чтения карт (статус команды InDataExchange; не является частью фактического APDU ответа), мы получаем 0x01 0x02 в качестве ответа (это APDU ответа IsoDepA) и мы получаем 0x9000 в качестве кода состояния. для APDU-оболочки считывателя карт (не является частью фактического ответного APDU).

InDataExchange с ДАННЫМИ = 0x01 0x02 0x03

> FF00000006 D440 01 010203 00
< D541 00 010203 9000

Таким образом, мы получаем код ошибки 0x00 от устройства чтения карт (статус команды InDataExchange; не является частью фактического APDU ответа), мы получаем 0x01 0x02 0x03 в качестве ответа (это APDU ответа IsoDepA) и мы получаем 0x9000 в качестве статуса. код для APDU-оболочки считывателя карт (не является частью фактического ответного APDU).

InDataExchange с ДАННЫМИ = 0x01 0x02 0x03 0x04

> FF00000007 D440 01 01020304 00
< D541 00 01020304 9000

Таким образом, мы получаем код ошибки 0x00 от устройства чтения карт (состояние команды InDataExchange; не является частью фактического APDU ответа), мы получаем 0x01 0x02 0x03 0x04 в качестве ответа (это APDU ответа IsoDepA) и мы получаем 0x9000 в качестве ответа. код состояния для APDU-оболочки считывателя карт (не является частью фактического ответного APDU).

Таким образом, мы получаем именно те данные, которые мы отправляем в качестве командного APDU в качестве ответного APDU (обратите внимание, что ни один из этих APDU не отформатирован в соответствии с ISO 7816-4, но это не имеет значения, поскольку эмуляция карты IsoPcdA работает с любым транспортным протоколом ISO 14443-4). формат).

Код состояния 0x9000 относится к инкапсуляции APDU считывателя карт (CLA=FF INS=00 P1P2=0000 Lc [PN542 COMMAND] Le=00), которая требуется в качестве Доступ к PN532 ACR122U осуществляется через интерфейс CCID (PC/SC). Это чистая инкапсуляция команд чтения, не имеющая ничего общего с обменом данными через ISO-DEP.

D440 01 [DATA] — это команда PN532 для обмена данными (например, APDU) через ISO-DEP, а D541 00 [DATA] — соответствующий ответ.

person Michael Roland    schedule 27.05.2013
comment
Во-первых, я хочу иметь возможность контролировать именно этот байт состояния (о котором вы говорите в последней строке). Текущая проблема заключается в том, что я могу вернуть только «успешные» R-APDU. Я хочу иметь возможность отвечать другим байтом состояния, отличным от 00 (например, с кодом состояния тайм-аута 01). - person Fons; 28.05.2013
comment
Кстати, это (mroland.at/fileadmin/mroland/tutorials/) твой? Я прочитал это вчера, и это заставило меня подумать, что управление полным ADPU с эмуляцией карты на Android возможно, потому что вы указали смарт-карты ISO-7816 как тег типа 4, что именно то, что первая ссылка в вопросе говорит, возможно с SCE на Android. - person Fons; 28.05.2013
comment
Управление полным APDU возможно (как я писал в своем ответе). Однако байт состояния, на который вы ссылаетесь, не является частью APDU. Этот байт состояния является частью связи между вашим приложением для чтения и вашим чипом для чтения. Вы никак не можете повлиять на это на уровне APDU. - person Michael Roland; 23.07.2013
comment
Да, это мой учебник. - person Michael Roland; 23.07.2013
comment
Все-таки эмулировать нормальное общение между ридером и нексусом 7 не совсем возможно. Когда я использую транссивер на IsoPcdA, аргумент, который я предоставляю, не содержит байтов SW. Они добавляются автоматически. Когда я предоставляю {0x01}, байты {0x90, 0x00} отображаются на другом конце, добавленном к 0x01. И отправка APDU нулевой длины также невозможна (например, mifare OK для аутентификации). У вас есть решение для этого? - person Fons; 24.07.2013
comment
Я только что протестировал с помощью Galaxy Nexus (CM 10) и ACR122U, используя код образца и команды, приведенные в моем ответе выше, и он работает, как и ожидалось (возможна любая связь ISO-DEP, никакие байты состояния не добавляются автоматически). - person Michael Roland; 25.07.2013
comment
Спасибо, отличная редакция! SW (9000) нельзя изменить, если что-то действительно пойдет не так, верно? Что вы не пробовали в коде, так это ответ нулевой длины (данные). Есть ли способ изменить байт состояния заголовка PN532? Например, ответ (как его видит преклир) как D541 13 9000 (я знаю, что это Mifare, а не 14443-4, но все же). Я думаю, нет? @Майкл - person Fons; 25.07.2013
comment
Правильно, если это слово состояния, на которое вы ссылаетесь: его нельзя изменить, и в этом нет смысла (это только перенос команды). Что касается ответа нулевой длины: я не тестировал, потому что мое приложение для Android просто повторяет все полученные команды в качестве ответа, и невозможно отправить пустую команду с помощью InDataExchange. Я не уверен, что пустые ответы допустимы в соответствии со спецификацией ISO-DEP. - person Michael Roland; 26.07.2013
comment
Опять же: установка байта состояния ответа InDataExchange невозможна и не имеет никакого смысла (поскольку этот байт состояния указывает только состояние выполнения команды для InDataExchange). Я не уверен, что вы имеете в виду под Mifare - здесь нет Mifare. Ответ на ошибку D541 13 9000 указывает на ошибку кадрирования RF. - person Michael Roland; 26.07.2013
comment
Кроме того, я бы не стал слишком долго останавливаться на деталях команд InDataExchange. Если вы используете правильный ридер (тот, который совместим с PC/SC и не злоупотребляет PC/SC в качестве протокола туннелирования команд, например, ACR122U и его производные), вы сможете прозрачно отправлять и получать правильно отформатированные APDU, как указано в ISO 7816-4. - person Michael Roland; 26.07.2013
comment
Ошибка, которую я имел в виду, была 14, а не 13. Моя ошибка :) Но, вероятно, это все равно не сработает. Спасибо, в любом случае! - person Fons; 26.07.2013
comment
Вы никогда не должны получать код ошибки 0x14 для InDataExchange с любой картой ISO-DEP. (Ошибка 14 указывает на ошибку аутентификации Mifare, которая может произойти только при использовании функций Mifare PCD.) - person Michael Roland; 26.07.2013