【问题标题】:NFC reader "SELECT (by AID)" APDU is not routed to Android deviceNFC 阅读器“SELECT(通过 AID)”APDU 未路由到 Android 设备
【发布时间】:2018-05-13 13:47:14
【问题描述】:

我有一个 ACR122U NFC 读取器/写入器连接到我的 Windows 机器并安装了 ACR122 驱动程序。

我尝试使用javax.smartcardio API 将 SELECT(通过 AID)ADPU 发送到我的 Android 设备(应该处于 HCE 模式)。

这是我的代码:

TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
CardTerminal terminal = terminals.get(0);
System.out.println(terminal.getName());
Card card = terminal.connect("*");
CardChannel channel = card.getBasicChannel();
execute(channel, new byte[] { (byte) 0xFF, 0x00, 0x51, (byte) 195, 0x00}, card);
execute(channel, new byte[] { (byte)0xFF, 0x00, 0x00, 0x00, 0x04,(byte)0xD4, 0x4A, 0x01, 0x00}, card); //InListPassiveTarget
execute(channel, new byte[] { (byte)0xFF, 0x00, 0x00, 0x00, 0x04,(byte)0xD4, 0x4A, 0x01, 0x00}, card); //InListPassiveTarget
execute(channel, new byte[] {0x00, (byte) 0xA4, 0x04, 0x00, 7,
                (byte)0xF0, 0x01, 0x02, 0x03, 0x04, (byte) 0x05, 0x07, 0}, card); //select AID

...

public static void execute(CardChannel channel, byte[] command, Card...cards) throws CardException {
    ByteBuffer r = ByteBuffer.allocate(1024);
    channel.transmit(bufferFromArray(command), r);
    System.out.println(convertBinToASCII(r.array(), 0, r.position()));
}

这是我得到的输出:

ACS ACR122 0 3B8F8001804F0CA000000306030000000000006B C3 D54B6300 D54B010108032004010203049000

我猜01020304 是我的 Android 设备向 NFC 阅读器提供的 UID。 SELECT APDU 不返回响应,它的长度为 0 字节。

在我的 Android 设备上,我有这项服务:

public class MyHostApduService extends HostApduService {

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("APDU", "APDU service was created.");
    }

    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
       Log.e("APDU", "command apdu: " + Arrays.toString(apdu));
       return new byte[2];
    }
    @Override
    public void onDeactivated(int reason) {
       Log.e("APDU", "ON DEACTIVATED.");
    }
}

但是processCommandAdpu 没有被调用。当 SELECT ADPU 应该发送给阅读器时,通过查看日志我找不到任何东西,所以看起来 ADPU 甚至没有到达 Android 设备。

这是 Android 项目的 apduservice.xml:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/servicedesc"
    android:requireDeviceUnlock="false" >
    <aid-group
        android:category="other"
        android:description="@string/aiddescription" >
        <aid-filter android:name="F0010203040507" />
    </aid-group>
</host-apdu-service>

此外,还有几个 ADPU 在传输时会使 NFC 阅读器有些卡住。例如,

execute(channel, new byte[] {(byte) 0xFF, 0x00, 0x00, 0x00, 0x02, (byte) 0xd4, 0x04}, card);

查询PN532芯片当前状态的伪APDU不返回任何响应。会不会是这个特定的读者有缺陷?我怎样才能检查它?


更新(基于discussion in chat):

使用第二个阅读器(相同型号,相同版本)的测试刚刚奏效。因此,可能是第一个阅读器上的一些模糊设置或阅读器出现故障。

两个阅读器的版本信息相同:

  • ACR122U固件版本:41435231323255323135 (-> ACR122U215)
  • PN532 版本:D503 32010607 9000 (-> PN532 v1.6)

【问题讨论】:

    标签: java nfc apdu hce acr122


    【解决方案1】:

    您使用 InListPassiveTarget 直接指示 ACR122U 内部的 PN532 NFC 芯片手动轮询标签。这实质上绕过了 ACR122U 的抽象层,允许您自动轮询标签并使用“标准 PC/SC”与枚举智能卡交换 APDU 命令。因此,通过 PC/SC 接口发送普通 APDU 将不起作用,并且 SELECT APDU 将永远不会到达 Android HCE 端。

    相反,您还需要通过直接与 PN532 传输模块对话来交换 APDU 命令。您可以通过将 APDU 命令包装在 InDataExchange 命令(或 InCommunicateThru,如果您需要控制 ISO/IEC 14443-4 标头字段)中来做到这一点。在您的情况下,包装的 SELECT(通过 AID)命令 APDU 看起来像:

    execute(channel, new byte[] {
        (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
        16,                // Lc = command length
        (byte)0xD4, 0x40,  // InDataExchange
        0x01,              // Tag #1 (equal to the tag number from the InListPassiveTarget response)
        0x00, (byte)0xA4, 0x04, 0x00,                         // APDU: SELECT (by AID)
              7,                                              // Lc = AID length
              (byte)0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, // AID = F0010203040507
              0x00,                                           // Le = max
    }, card);
    

    会不会是这个特定的阅读器有缺陷?

    是的,情况可能是这样,但我对此表示怀疑。请注意,有许多不同版本的 ACR122U 固件,其中大多数似乎存在设计缺陷。尤其是某些版本的阅读器执行自动标签枚举而有些不执行,并且可用的 API 在该阅读器的不同版本之间发生巨大变化,这使得为该设备编程变得困难。

    更新:更多观察结果...

    • 对 InListPassiveTarget 命令的响应不包含 ATS 数据(在 UID 字段之后)。也许您的阅读器在标签选择期间没有执行自动 RATS。这可以使用 SetParameters 命令启用(在 InListPassiveTarget 之前):

      execute(channel, new byte[] {
          (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
          3,                 // Lc = command length
          (byte)0xD4, 0x12,  // InDataExchange
          (1<<4),            // fAutomaticRATS = 1
      }, card);
      

      您也可以尝试使用 InCommunicateThru 手动发送 RATS 命令:

      execute(channel, new byte[] {
          (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
          4,                 // Lc = command length
          (byte)0xD4, 0x42,  // InCommunicateThru
          (byte)0xE0, 0x80,  // RATS (FSD = 256, CID = 0)
      }, card);
      

      之后,您可以尝试使用 InCommunicateThru 和原始 ISO/IEC 14443-4 块与卡进行通信:

      execute(channel, new byte[] {
          (byte)0xFF, 0x00, 0x00, 0x00,  // direct PN532 command
          16,                // Lc = command length
          (byte)0xD4, 0x42,  // InCommunicateThru
          0x02,              // PCB (I-block, change to 0x03 for the next block)
          0x00, (byte)0xA4, 0x04, 0x00,                     // APDU: SELECT (by AID)
            7,                                              // Lc = AID length
            (byte)0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, // AID = F0010203040507
            0x00,                                           // Le = max
      }, card);
      
    • ATQA 0803 看起来很奇怪。尤其是位帧防冲突字段中的 0x03 表明该字段中有多个目标(因为符合标准的标签只会在位帧防冲突字段中设置一个位)。 请注意,这不是真的。对 InListPassiveTarget 的响应中的 ATQA 以小端方式传输。因此,位帧防冲突值为 0x08(= 有效/合规),专有字段中的值为 0x03。

    • 您的阅读器不响应某些 PN532 命令确实很奇怪(特别是因为固件版本 32010607 看起来不错)。我用另一台 ACR122U 测试了一些对你来说失败的命令,它们成功完成了......

    【讨论】:

    • 嗨迈克尔,非常感谢您的回答。我之前尝试过您的建议,然后又尝试了一次,不幸的是它似乎不起作用,当我尝试传输此 APDU 时程序被阻止了。我不相信这是 Android 端的问题,因为当我使用另一个发送 select AID APDU 的 Android 设备时,会发生这种通信并启动服务。
    • 我在使用 libnfc 库时观察到了相同的行为。 =&gt; 6f 09 00 00 00 00 00 00 00 00 ff 00 00 00 04 d4 4a 01 00 &lt;= 80 0e 00 00 00 00 00 02 fe 00 d5 4b 01 01 08 03 20 04 01 02 03 04 90 00 - 找到标签。 =&gt; 6f 14 00 00 00 00 00 00 00 00 ff 00 00 00 0f d4 40 01 a4 04 00 07 f0 01 02 03 04 05 07 00 - select AID ADPU 这似乎与您提议的完全一样,然后它就超时了。没有收到回复。
    • stackoverflow.com/questions/50338113/… 这是我提出的问题,提供了有关运行 libnfc 示例时得到的输出的更多信息。
    • 基本上,我对此一无所知。 libnfc 似乎没有工作。我找到了一些 pssc python 包装器并尝试传输相同的 APDU(用 0xFF000000 包装)它也没有工作,只是超时。
    • @cliffroot 那很奇怪。请注意,在上面的 USB 帧中,您似乎缺少 APDU 的 CLA 字节(在 d4 40 01a4 04 00 之间添加 00 + 调整长度),但我怀疑这也会导致超时。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-24
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多