I2Cバス上のMITM
I2Cバスで選択したスレーブ応答を変更できるモジュールを設計しようとしています。これは元のバス構成です(わかりやすくするためにプルアップと電源接続は示していません)。 このバスには2つのデバイスしかなく、100kHzしかありません。コントローラーMCU(I2Cマスター)およびRFIDカードリーダー(I2Cスレーブ)NXP PN512。コントローラーのファームウェアを変更したり、I2Cバスのトランザクションを変更したりできません。良い点は、コントローラーが2種類のトランザクションのみを送信することです。 Master (Write Register) - <s><address+W><register number><data><p> Master (Read Register) - <s><address+W><register number><p><s><address+R><data><p> 私がしたいことは、マスターレジスタの読み取り中に選択したデータバイトを自分のバイトで置き換えることです。MCUが読み取りたいレジスタ番号をUART(921.6kbaud)経由でPCに送信できます。C / C ++またはPythonで処理できます。値を置き換える必要のあるレジスター番号を受け取ったら、偽のバイトをデバイスに送り返すことができます。コントローラーに送り返して、元のカードの応答を置き換えます。 最初に、I2Cバスを2つのバスに分割しました。 Arduino Nanoを試し、その後クロックストレッチを使用してCPLDを試しました。MCUコントローラーに面したATmega328ハードウェアI2Cは、前の停止サイクルの5usより前に開始シーケンスが生成されることがあったため、追いつくことができませんでした。したがって、時々、AVRは読み取りトランザクションをNAKしていました。CPLDは、バスストレッチがMCUで無効になっていることが判明した停止/開始速度を処理できました。 マスターレジスタの読み取りは、その後に読み取りが続くと確信しているので、1バイトの書き込みを検出することで、読み取りを「予測」できるというアイデアを思いつきました。次のリードサイクルアドレス書き込み中に、スレーブからバイトを取り込むのに十分な時間があったようです。それはうまくいきませんでした。バストランザクションは最初(約最初の5秒間)は正常に見えましたが、コントローラーはバス上のすべての通信を停止し、タグの読み取りと直接通信していないことを検出したかのように処理していました。 カードリーダーは、マスターへの割り込みを生成することもできます。IRQは、タイマーまたはイベントベースです。この問題は、バスに本来導入されていた遅延が原因であると考えています。私は間違っていたかもしれませんが、別の「ゼロ遅延」設計を思いつきました。 私が考えているのは、SDAラインを切断し、SCLラインをマスターとスレーブの間に接続したままにすることだけです。このようにして、データラインのバイトをどちらの方向でも置き換えることができます。バスサイクルに基づいてSDAラインの方向を制御する必要があるため、設計がより複雑であることがわかりました。バストランザクションを処理し、16進バイトを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 : …