I2C总线上的MITM
我一直在尝试设计一个模块,该模块将允许我修改I2C总线上的选定从属响应。这是原始总线配置(为清楚起见,未显示上拉和电源连接: 该总线上只有2个设备,并且只有100kHz。控制器MCU(I2C主设备)和RFID读卡器(I2C从设备)NXP PN512。我无法修改控制器固件或更改I2C总线事务。好消息是控制器仅发送两种交易类型: Master (Write Register) - <s><address+W><register number><data><p> Master (Read Register) - <s><address+W><register number><p><s><address+R><data><p> 我想做的是用我自己的字节替换在主寄存器读取期间选择的数据字节。我可以通过UART(921.6kbaud)将MCU希望读取的寄存器号发送到我的PC。我可以在那里用C / C ++或Python处理它们。当我收到需要替换其值的寄存器号时,可以将假字节发送回我的设备,它将负责将其发送回控制器,以替换原始卡的响应。 首先,我将I2C总线分为两部分: 我尝试了Arduino Nano,后来尝试了使用时钟扩展的CPLD。面对MCU控制器的ATmega328硬件I2C不能跟上,因为有时启动序列的产生早于上一个停止周期后的5us。因此,AVR时不时要进行NAK读取事务。CPLD可以处理停止/启动速度,结果证明在MCU中禁用了总线扩展。 我想出了一个可以通过检测单字节写入来“预测”主寄存器读取的想法,因为我确信它后面会进行读取。在下一个读周期地址写入期间,似乎有足够的时间从从设备引入字节。那不是很有效。总线事务在开始时(大约前5秒)似乎还不错,但随后控制器停止了总线上的所有通信,就好像它检测到不是在直接与标签读取对话一样。 读卡器还可以产生对主机的中断。IRQ是基于计时器或事件的。我将问题归因于本来是在总线上引入的延迟。我可能错了,但我想出了另一种“零延迟”设计。 我的想法是,我只能断开SDA线,而使SCL线保持连接在主机和从机之间。这样,我仍然可以在任一方向上替换数据线上的字节。由于我必须根据总线周期来控制SDA线的方向,因此设计变得更加复杂。这是处理总线事务并通过UART将十六进制字节发送到计算机的VHDL代码。从计算机接收字节尚未实现: library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity I2C_Sniffer is port ( clk : in std_logic; scl_master : in std_logic; sda_master : inout std_logic; sda_slave : …