如何通过程序与JCOP 4.7 R4.10.12模拟器通信并发送APDU
适配JCOP 4.7 R4.10.12的APDU收发工具及协议适配方案
背景
JCOP模拟器是NXP推出的Eclipse插件,可模拟JCOP操作系统与JavaCard虚拟机,但无法直接以PC/SC读卡器形式与终端通信,而是通过专属网络协议交互,默认监听接触式、非接触式、调试三个端口。此前基于MUSCLE项目ifhandler.c开发的JCOPVR等工具,可实现PC/SC与模拟器的通信,但因新版本模拟器协议变更,这类工具已失效。
需求
- 支持JCOP 4.7 R4.10.12版本的程序化APDU收发工具
- 该版本模拟器的网络协议资料,用于修改旧工具适配新环境
可用解决方案
1. 官方工具优先
NXP官方的JCOP Tools套件中,对应版本可能包含适配新版模拟器的APDU调试组件。优先检查JCOP Tools安装包中的JCOP Shell或APDU Terminal,这类工具通常原生支持连接新版模拟器发送APDU指令。
2. 协议逆向适配
若没有现成工具,可通过以下方式分析新版协议:
- 使用Wireshark抓取模拟器与官方工具之间的网络通信包,对比旧协议(旧代码采用
0x1开头的4字节帧头+APDU数据格式),定位新版协议的帧结构变化(如头字节、长度编码、校验机制等) - 重点监听默认端口:接触式端口9020、非接触式端口9021、调试端口9022,抓取对应端口的数据包进行分析
3. 社区开源项目
部分开源社区有开发者维护的JCOP模拟器适配工具,可搜索关键词JCOP 4.7 R4.10.12 PC/SC或JCOP simulator protocol,查找是否有已适配的代码分支或修改方案。
旧版失效代码片段(ifhandler.c)
RESPONSECODE IFDHTransmitToICC ( DWORD Lun, SCARD_IO_HEADER SendPci, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength, PSCARD_IO_HEADER RecvPci ) { /* This function performs an APDU exchange with the card/slot specified by Lun. The driver is responsible for performing any protocol specific exchanges such as T=0/1 ... differences. Calling this function will abstract all protocol differences. SendPci Protocol - 0, 1, .... 14 Length - Not used. TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F 0x00) TxLength - Length of this buffer. RxBuffer - Receive APDU example (0x61 0x14) RxLength - Length of the received APDU. This function will be passed the size of the buffer of RxBuffer and this function is responsible for setting this to the length of the received APDU. This should be ZERO on all errors. The resource manager will take responsibility of zeroing out any temporary APDU buffers for security reasons. RecvPci Protocol - 0, 1, .... 14 Length - Not used. Notes: The driver is responsible for knowing what type of card it has. If the current slot/card contains a memory card then this command should ignore the Protocol and use the MCT style commands for support for these style cards and transmit them appropriately. If your reader does not support memory cards or you don't want to then ignore this. RxLength should be set to zero on error. returns: IFD_SUCCESS IFD_COMMUNICATION_ERROR IFD_RESPONSE_TIMEOUT IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED*/ int ret; dbg_log("JCOP.Transmit(): Lun 0x%x\n", Lun); dbg_log("JCOP.Transmit(): io_hdr proto %d, length %d\n", SendPci.Protocol, SendPci.Length); dbg_log("JCOP.Transmit(): txb 0x%x, txbl %d, rxb 0x%x, rxbl %d\n", TxBuffer, TxLength, RxBuffer, *RxLength); if (JCOP_socket < 0){ dbg_log("JCOP.Transmit(): invalid jcop socket\n"); return IFD_COMMUNICATION_ERROR; } if (TxLength >= 256){ dbg_log("JCOP.Transmit(): invalid transmit buffer size %d\n", TxLength); jcop_close(); return IFD_COMMUNICATION_ERROR; } // copy data from send_buffer to JCOP_buffer and send JCOP_buffer[0] = 0x1; JCOP_buffer[1] = 0x0; JCOP_buffer[2] = TxLength/256; JCOP_buffer[3] = TxLength%256; memcpy(JCOP_buffer+4, TxBuffer, TxLength); dbg_ba2s(JCOP_buffer, TxLength+4); dbg_log("jcop send: %s\n", DBG_buf); // send apdu ret = _write(JCOP_socket, JCOP_buffer, TxLength + 4); if (ret < 0){ dbg_log("Failed to transmit to jcop\n"); jcop_close(); return IFD_COMMUNICATION_ERROR; } // read apdu ret = jcop_read(0x1); if (ret < 0){ dbg_log("Failed to receive apdu response\n"); return IFD_COMMUNICATION_ERROR; } *RxLength = ret - 4; memcpy(RxBuffer, JCOP_buffer+4, *RxLength); dbg_ba2s(RxBuffer, *RxLength); dbg_log("jcop response apdu: %s\n", DBG_buf); return IFD_SUCCESS; }
内容的提问来源于stack exchange,提问作者martin rupp
相关产品推荐
相关产品推荐

