|
|
@@ -0,0 +1,148 @@ |
|
|
|
# i2c-stub toy |
|
|
|
|
|
|
|
Recently I had a chance to play with ``i2c-stub``. The goal was to send and receive encrypted data to/from I2C connected device. I didn't want to play with real I2C device, so I needed to emulate it somehow, which is possible with ``i2c-stub`` on linux. Here below is description how it was done. |
|
|
|
|
|
|
|
# Requirements |
|
|
|
|
|
|
|
The solution needs to be implemented in C and have following functionalities |
|
|
|
* Possibility to connect to I2C slave |
|
|
|
* Send encrypted data |
|
|
|
* Receive and decrypt data |
|
|
|
* Possibility to check connection status |
|
|
|
|
|
|
|
# The code |
|
|
|
|
|
|
|
The code itself is here. To compilie with ``gcc`` simply download and ``make``. |
|
|
|
|
|
|
|
## Initialization |
|
|
|
|
|
|
|
In order to use the code (read/write data to I2C) I'm using ``i2c-stub`` linux |
|
|
|
module and i2c-tools package (ArchLinux). ``i2c-stub`` creates a fake I2C adapter(Controller/Master) and emulates i2C hardware (using array to store data). We also will need ``i2c-dev`` module as a frontend. |
|
|
|
|
|
|
|
Following command will load the module, initialize slave device with an address 0x03, and read it's initial state: |
|
|
|
|
|
|
|
``` |
|
|
|
> modprobe i2c-dev |
|
|
|
> modprobe i2c-stub chip_addr=0x03 |
|
|
|
|
|
|
|
> i2cdetect -l |
|
|
|
i2c-1 i2c i915 gmbus dpc I2C adapter |
|
|
|
i2c-2 i2c i915 gmbus dpd I2C adapter |
|
|
|
... |
|
|
|
i2c-8 smbus SMBus stub driver SMBus adapter <-- this one |
|
|
|
... |
|
|
|
|
|
|
|
> i2cdump -y 8 0x03 |
|
|
|
No size specified (using byte-data access) |
|
|
|
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef |
|
|
|
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
We can see that module was loaded. ``i2cdetect`` as detected is as a character device ``/dev/i2c-8`` and ``i2c-dump`` shows memory state of slave device with an ID ``0x03``. |
|
|
|
|
|
|
|
|
|
|
|
## Sending data |
|
|
|
|
|
|
|
Test program has ``-s`` option that needs to be used in order to send data. As an argument, device ID needs to be provided. |
|
|
|
|
|
|
|
``` |
|
|
|
> ./bin/main -s 8 && echo $? |
|
|
|
0 |
|
|
|
``` |
|
|
|
|
|
|
|
On a success program return 0. We can now verify if data has been stored in the i2c device with ``i2cdump``. |
|
|
|
|
|
|
|
``` |
|
|
|
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef |
|
|
|
00: 1f f8 47 8e 7f 24 1d 2b 47 ca 64 be ce 0a 3f bd ??G??$?+G?d????? |
|
|
|
10: 08 1c 05 87 b0 31 6c 85 46 94 6f c8 9e 49 dd b2 ?????1l?F?o??I?? |
|
|
|
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
``` |
|
|
|
|
|
|
|
Before sending program uses Poly1305-ChaCha20 to encrypt and authenticate data. |
|
|
|
|
|
|
|
## Receiving data |
|
|
|
|
|
|
|
Test program has ``-r`` option to indicate that user want's to receive data from I2C device. On exit program prints received data. |
|
|
|
|
|
|
|
``` |
|
|
|
[root@cryptoden final]# ./bin/main -r 8 |
|
|
|
RECEIVED DATA: |
|
|
|
HELLO WORLD!!! |
|
|
|
``` |
|
|
|
|
|
|
|
As data is authenticated any change to data stored in the I2C will result |
|
|
|
in decryption error. In order to see this behaviour one can dump the I2C |
|
|
|
memory, change it, load to I2C and try to read again. Let's see this: |
|
|
|
|
|
|
|
``` |
|
|
|
> i2cdump -y 8 0x03 b > dump |
|
|
|
> cat dump |
|
|
|
[root@cryptoden ~]# cat dump |
|
|
|
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef |
|
|
|
00: 1f f8 47 8e 7f 24 1d 2b 47 ca 64 be ce 0a 3f bd ??G??$?+G?d????? |
|
|
|
10: 08 1c 05 87 b0 31 6c 85 46 94 6f c8 9e 49 dd b3 ?????1l?F?o??I?? |
|
|
|
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
|
|
|
|
|
|
|
## Here I modify 32-nd byte from b3 to b2 and load data to i2c-stub |
|
|
|
> i2c-stub-from-dump 0x03 dump |
|
|
|
256 byte values written to 8-0003 |
|
|
|
|
|
|
|
## Trying to read |
|
|
|
> ./bin/main -r 8 |
|
|
|
[i2c_recv() src/i2c.c:165] Error occured when decrypting |
|
|
|
[i2c_recv() src/i2c.c:172] ERROR: can't receive encrypted data |
|
|
|
[test_receive() src/main.c:88] Error occured when receiving data |
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
## Testing |
|
|
|
Program has a ``-t`` option which can be used to test program and see |
|
|
|
that connection stays persistent after connecting to the device. |
|
|
|
|
|
|
|
``` |
|
|
|
> ./bin/main -t 8 && echo $? |
|
|
|
0 |
|
|
|
``` |