NFC阅读器“SELECT(通过AID)”APDU不会路由到Android设备

我有一台ACR122U NFC读写器连接到安装了ACR122驱动程序的Windows机器。

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

这是我的代码:

 TerminalFactory factory = TerminalFactory.getDefault(); List 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:

      

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

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

这是一个伪APDU来查询PN532芯片的当前状态,不会返回任何响应。 难道这个特定的读者有缺陷吗? 我怎么检查呢?


更新 (根据聊天中的讨论 ):

使用第二个阅读器(相同型号,相同版本)进行测试。 所以它可能是第一个读者的一些模糊设置或读者只是出现故障。

两个读者都有相同的版本信息:

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

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

相反,您还需要通过直接与PN532传输模块通信来交换APDU命令。 您可以通过在InDataExchange命令中包装APDU命令来实现此目的(如果您需要控制ISO / IEC 14443-4标头字段,则可以使用InCommunicateThru)。 在您的情况下,包装的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是以little endian传输的。 因此,位帧防冲突值为0x08(=有效/兼容),并且专有字段中的值为0x03。

  • 确实,您的读者对某些PN532命令没有响应(特别是因为固件版本32010607看起来很好),这确实很奇怪。 我用另一台ACR122U测试了一些失败的命令,并且它们成功完成了......