Marius Schwarz c7f754f7ed initial-commit | 3 anni fa | |
---|---|---|
.. | ||
Makefile.simpleserial | 3 anni fa | |
README.md | 3 anni fa | |
simpleserial.c | 3 anni fa | |
simpleserial.h | 3 anni fa |
All communication is initiated by the capture board. The capture board begins communication by sending a packet:
[cmd, data_0, data_1, ..., data_n, '\n']
where cmd
is an ASCII character indicating the desired command and data
is
an ASCII representation of the data (i.e. 0xAA
will be 'A'
, 'A'
)
The length of data is fixed by the firmware.
If the target board needs to respond with data, it sends back:
['r', data_0, data_1, ..., data_n, '\n']
Again, data_n
is an ASCII representation of the data.
Whether or not the device sends back data, the device will send back an ack to tell the capture board that it is done its operation:
['z', status, '\n']
Where status is an 8-bit binary number indicating the result/status of the operation. For example, most functions use 0x00 to indicate success.
The default baud rate is 38400bps.
The same as SimpleSerial v1.1, except the ack packet is not included.
Variable length commands have been added, primarily to support masked AES. Variable length commands are decided by firmware. In the case of a variable length command, the send command will instead be:
[cmd, len, data_0, data_1, ..., data_n, '\n']
The following commands are reserved by SimpleSerial v1:
'v'
: Get Simpleserial version (len=0)'y'
: Get the number of Simpleserial commands on the target'w'
: Get Simpleserial commandsAll communication is initiated by the capture board. The capture board begins communication by sending a packet:
[cmd, scmd, dlen, data_0, data_1, ..., data_n, CRC (poly=0x4D)]
cmd indicates the desired command, scmd
indicates a sub-command, dlen
is the
length of the data, data is binary data, and the crc is a CRC of polynomial 0x4D
of the entire packet (from cmd
to data_n
). All bytes in the packet may take
any 8-bit binary value, except dlen
, which is limited to less than 250.
Therefore, only 249 bytes can be sent per packet.
If the target board needs to respond with data, it sends back:
[cmd, dlen, data_0, data_1, ..., data_n, CRC (poly=0x4D)]
Whether or not the device sends back data, the device will send back an error packet to tell the capture board that it is done its operation:
['e', 0x01, error, CRC (poly=0x4D)]
Before being sent, all packets are Consistent Overhead Byte Stuffing (COBS) and null terminated:
[overhead_byte, [packet], 0x00]
.
The following standard errors are used:
0x00 - OK
0x01 - Invalid command
0x02 - Bad CRC
0x03 - Timeout
0x04 - Invalid length
0x05 - Unexpected frame byte (0x00)
0x06 - Reserved
...
0x0F - Reserved
Commands may use additional error codes to indicate the result of an operation.
The default baud rate is 230400bps.
NOTE: Only the XMEGA and STM32* devices currently switch to this higher baud rate when building for SimpleSerial V2.1. Other devices will likely communicate at 38400bps instead.
The following commands are reserved by SimpleSerial v2:
'v'
: Get simpleserial version (len=0)'w'
: Get simpleserial commandsAs of ChipWhisperer 5.6.1, this SimpleSerial version is deprecated because it used an incorrect constant for its CRC (0xA6 instead of 0x4D)
You can use the C SimpleSerial library to listen to and send packets containing commands, data, etc.
There are four exposed methods in the C library.
simpleserial_init
This sets up the SimpleSerial module and prepares any internal commands. It mostly there for future usage.
Calling it is as simple as:
#include "simpleserial.h"
// ..snip
simpleserial_init();
simpleserial_addcmd
Adds a listener on the target for a specific command. Depending on the version of SimpleSerial you are using, the arguments are different.
Note: the C implementation of the SimpleSerial can only hold a maximum of 16 active command.
Depending on whether we are using V1.* or V2, it takes the following ordered arguments:
char
- the command the target needs to listen for.unsigned int
- the amount of data bytes expected. The maximum is 64 bytes.(uint8_t*, uint8_t) -> uint8_t
- the handler for the command taking the
data buffer and the actual data buffer length in bytes and returning a
status code.char
- the command the target needs to listen for.unsigned int
- the amount of data bytes expected. The maximum is 192 bytes.(uint8_t, uint8_t, uint8_t, uint8_t*) -> uint8_t
- the handler for the
command taking the arguments command, sub-command, actual data buffer
length and the data buffer in bytes, in that order, and returning a
status code.Returns an int
which is 1
if the maximum expected data buffer length is
exceeded and if the maximum number of commands has been reached. Will return 0
otherwise.
'z'
message, as described above.The following is a SimpleSerial V2 example.
#include "simpleserial.h"
uint8_t set_key(uint8_t cmd, uint8_t scmd, uint8_t dlen, uint8_t* data)
{
// ...snip
return 0;
}
uint8_t encrypt_plaintext(uint8_t cmd, uint8_t scmd, uint8_t dlen, uint8_t* data)
{
// ...snip
return 0;
}
// ... snip
simpleserial_addcmd('k', 16, set_key);
simpleserial_addcmd('p', 16, encrypt_plaintext);
simpleserial_put
Write some data to the serial port, which should send a packet from the target board to the capture board.
This function takes the following ordered arguments:
char
- the command for the capture board (e.g. 'z'
for ack, or 'e'
for error).uint8_t
- the size of the data buffer.uint8_t*
- the data buffer of the packet send.The following is a SimpleSerial V2 example (although this has no impact on the
usage of the simpleserial_put
function).
#include "simpleserial.h"
uint8_t encrypt_plaintext(uint8_t cmd, uint8_t scmd, uint8_t dlen, uint8_t* data)
{
// ...snip (do the actual encryption).
// Send the result back to the capture board.
simpleserial_put('r', 16, result_buffer);
return 0;
}
// ... snip
simpleserial_addcmd('p', 16, encrypt_plaintext);
simpleserial_get
Attempt to process a received command. If a packet from the capture board is found relevant callback function(s) are called.
This is mostly used at the end of binaries to keep checking for commands being check.
It might return without calling a callback for several reasons:
#include "simpleserial.h"
// ...snip
// Add a listener
simpleserial_addcmd('p', 16, encrypt);
// Keep check if a command was send fitting one of the listeners.
while(1)
simpleserial_get();