无法使用 nfc_initiator_transceive_bytes() 使用 libnfc 发​​送大型 APDU 命令

Posted

技术标签:

【中文标题】无法使用 nfc_initiator_transceive_bytes() 使用 libnfc 发​​送大型 APDU 命令【英文标题】:Cannot send large APDU commands with libnfc using nfc_initiator_transceive_bytes() 【发布时间】:2017-12-14 19:39:46 【问题描述】:

我正在尝试围绕libnfc 构建一个C++ 包装器,以便在我的android 和PN532 RFID 模块之间进行通信。

这对我帮助很大:http://nfc-tools.org/index.php/Libnfc:APDU_example

此代码用于发送 APDU 命令,其中正文包含在 message 中(我不发送任何标头字节等)并将响应读入 response

问题:如果 message 超过 262 个字符,则会收到 检测到缓冲区溢出 错误。否则它工作得很好。我什至不认为错误是由 NFC 库引发的。

bool send(const std::string &message, std::string &response)
    std::vector<uint8_t> apduCmd(message.begin(), message.end());
    uint8_t *capdu = &apduCmd[0];
    size_t capdulen = apduCmd.size();
    uint8_t rapdu[10];
    size_t rapdulen = 10;

    // BUFFER OVERFLOW HERE
    int res = nfc_initiator_transceive_bytes(m_nfcDevice, capdu, capdulen, rapdu, rapdulen, 500);
    if (res<0) 
        return false;
    

    if(res<2 || rapdu[res-2] != 0x90 || rapdu[res-1] != 0x00)
        return false;
    

    // byteArrayToString omitting the last two bytes
    response = byteArrayToString(rapdu, 0, res-2);
    return true;

【问题讨论】:

您可能需要寻找对扩展 APDU 的支持 - 问题可能是,您的 Android 设备不支持数据长度 > 255 字节的 APDU cla[1] + ins[1] + param[2] + lc[1] + data[255] + le[1] = 261 bytes 【参考方案1】:

262 字节的限制是对 PN532 NFC 芯片施加的硬限制。这是可以在一个 InDataExchange 命令中发送(和接收)的原始数据的最大大小。 libnfc 明确地对方法 nfc_initiator_transceive_bytes() 强制执行此限制(请参阅 the definition of abtCmd in pn53x_initiator_transceive_bytes() 和 definition of PN53x_EXTENDED_FRAME__DATA_MAX_LEN)。

您可以做些什么来克服此限制,即编写自己的 ISO/IEC 14443-4 块(使用 InCommunicateThru,即 nfc_initiator_transceive_bytes() 关闭 m_nfcDevice-&gt;bEasyFraming。虽然每个帧仍将限制为 263 字节( PN532 实际上允许 InCommunicateThru 使用 264 字节,但 libnfc 似乎将其限制为 263 字节),然后您可以将扩展长度的 APDU 打包到多个 ISO/IEC 14443-4 I 块中。但是,您需要处理整个 ISO/自行构建 IEC 14443-4 框架(这意味着您还必须注意接收确认等)

最后,由于另一个通信端点是 Android 设备:许多 Android 设备不支持扩展长度的 APDU。因此,即使您发送更长的 APDU,您也可能无法在 Android 端接收和处理它们。另外,请注意,您应该发送符合 ISO/IEC 7816-4 中定义的结构的正确 APDU(即具有有效标头和长度字段的 APDU),否则在与某些设备通信时可能会遇到问题。

【讨论】:

感谢您提供如此详细的回答;)好吧,我想我将不得不发送多个块并自己实现协议 @OmarAflak 更简单的选择可能是将数据拆分到多个 APDU 并在 APDU 之上实现您的协议。在这种情况下,您不需要太在意时间(如果您自己处理 ISO/IEC 14443-4 传输,则需要这样做)。

以上是关于无法使用 nfc_initiator_transceive_bytes() 使用 libnfc 发​​送大型 APDU 命令的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 StorageClass 配置卷 - 无法获取存储帐户的存储密钥

Worklight Studio 和本地开发,有时无法使用 Java 类,有时无法使用 HTML 文件

ADB无法使用解决办法

Ubuntu 80端口无法使用-非root用户无法使用1024以下端口

无法在 SQL Server 视图中使用工作查询:“IS”无法识别“>”无法识别

LINUX下的mail\mailx为啥无法使用外部SMTP发邮件