diff options
| author | J08nY | 2019-11-21 19:10:50 +0100 |
|---|---|---|
| committer | J08nY | 2019-11-21 19:10:50 +0100 |
| commit | c8d0bff46001bd5636825c5b0bb4c896cb34a4e6 (patch) | |
| tree | 2b3029c6ca37e56e86daa34069ab39da3b1a5400 /pyecsca/codegen/simpleserial | |
| download | pyecsca-codegen-c8d0bff46001bd5636825c5b0bb4c896cb34a4e6.tar.gz pyecsca-codegen-c8d0bff46001bd5636825c5b0bb4c896cb34a4e6.tar.zst pyecsca-codegen-c8d0bff46001bd5636825c5b0bb4c896cb34a4e6.zip | |
Initialize.
Diffstat (limited to 'pyecsca/codegen/simpleserial')
| -rw-r--r-- | pyecsca/codegen/simpleserial/Makefile.simpleserial | 26 | ||||
| -rw-r--r-- | pyecsca/codegen/simpleserial/simpleserial.c | 150 | ||||
| -rw-r--r-- | pyecsca/codegen/simpleserial/simpleserial.h | 42 |
3 files changed, 218 insertions, 0 deletions
diff --git a/pyecsca/codegen/simpleserial/Makefile.simpleserial b/pyecsca/codegen/simpleserial/Makefile.simpleserial new file mode 100644 index 0000000..47a0d1e --- /dev/null +++ b/pyecsca/codegen/simpleserial/Makefile.simpleserial @@ -0,0 +1,26 @@ +SRC += simpleserial.c +VPATH += :$(FIRMWAREPATH)/simpleserial/ +EXTRAINCDIRS += $(FIRMWAREPATH)/simpleserial/ + +SS_VERS_ALLOWED = SS_VER_1_0 SS_VER_1_1 + +define SS_VERS_LIST + + +---------+--------------+ + | Version | SS_VER value | + +---------+--------------+ + | V1.0 | SS_VER_1_0 | + | V1.1 | SS_VER_1_1 | + +---------+--------------+ + +endef + +# SimpleSerial version +# To change this, define SS_VER before including this file +ifeq ($(SS_VER),) + SS_VER = SS_VER_1_1 +else ifeq ($(filter $(SS_VER),$(SS_VERS_ALLOWED)),) + $(error Invalid SimpleSerial version: $(SS_VER); allowed verions: $(SS_VERS_LIST)) +endif + +CDEFS += -DSS_VER=$(SS_VER)
\ No newline at end of file diff --git a/pyecsca/codegen/simpleserial/simpleserial.c b/pyecsca/codegen/simpleserial/simpleserial.c new file mode 100644 index 0000000..8205ed4 --- /dev/null +++ b/pyecsca/codegen/simpleserial/simpleserial.c @@ -0,0 +1,150 @@ +// simpleserial.c + +#include "simpleserial.h" +#include <stdint.h> +#include "hal.h" + +typedef struct ss_cmd +{ + char c; + unsigned int len; + uint8_t (*fp)(uint8_t*, uint16_t); +} ss_cmd; + +#define MAX_SS_CMDS 26 +static ss_cmd commands[MAX_SS_CMDS]; +static int num_commands = 0; + +#define MAX_SS_LEN 256 + +#define SS_VER_1_0 0 +#define SS_VER_1_1 1 + +static char hex_lookup[16] = +{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +int hex_decode(int len, char* ascii_buf, uint8_t* data_buf) +{ + for(int i = 0; i < len; i++) + { + char n_hi = ascii_buf[2*i]; + char n_lo = ascii_buf[2*i+1]; + + if(n_lo >= '0' && n_lo <= '9') + data_buf[i] = n_lo - '0'; + else if(n_lo >= 'A' && n_lo <= 'F') + data_buf[i] = n_lo - 'A' + 10; + else if(n_lo >= 'a' && n_lo <= 'f') + data_buf[i] = n_lo - 'a' + 10; + else + return 1; + + if(n_hi >= '0' && n_hi <= '9') + data_buf[i] |= (n_hi - '0') << 4; + else if(n_hi >= 'A' && n_hi <= 'F') + data_buf[i] |= (n_hi - 'A' + 10) << 4; + else if(n_hi >= 'a' && n_hi <= 'f') + data_buf[i] |= (n_hi - 'a' + 10) << 4; + else + return 1; + } + + return 0; +} + +// Callback function for "v" command. +// This can exist in v1.0 as long as we don't actually send back an ack ("z") +uint8_t check_version(uint8_t* v, uint16_t len) +{ + return 0x00; +} + +// Set up the SimpleSerial module by preparing internal commands +// This just adds the "v" command for now... +void simpleserial_init() +{ + simpleserial_addcmd('v', 0, check_version); +} + +int simpleserial_addcmd(char c, unsigned int len, uint8_t (*fp)(uint8_t*, uint16_t)) +{ + if(num_commands >= MAX_SS_CMDS) + return 1; + + if(len > MAX_SS_LEN) + return 1; + + commands[num_commands].c = c; + commands[num_commands].len = len; + commands[num_commands].fp = fp; + num_commands++; + + return 0; +} + +void simpleserial_get(void) +{ + char ascii_buf[2*MAX_SS_LEN]; + uint8_t data_buf[MAX_SS_LEN]; + char c; + + // Find which command we're receiving + c = getch(); + + int cmd; + for(cmd = 0; cmd < num_commands; cmd++) + { + if(commands[cmd].c == c) + break; + } + + // If we didn't find a match, give up right away + if(cmd == num_commands) + return; + + // Receive characters until we fill the ASCII buffer + int i = 0; + for(; i < 2*commands[cmd].len; i++) + { + c = getch(); + + // Check for early \n + if(c == '\n' || c == '\r') + break; + + ascii_buf[i] = c; + } + + // ASCII buffer is full: convert to bytes + // Check for illegal characters here + if(hex_decode(i, ascii_buf, data_buf)) + return; + + // Callback + uint8_t ret[1]; + ret[0] = commands[cmd].fp(data_buf, i); + + // Acknowledge (if version is 1.1) +#if SS_VER == SS_VER_1_1 + simpleserial_put('z', 1, ret); +#endif +} + +void simpleserial_put(char c, int size, uint8_t* output) +{ + // Write first character + putch(c); + + // Write each byte as two nibbles + for(int i = 0; i < size; i++) + { + putch(hex_lookup[output[i] >> 4 ]); + putch(hex_lookup[output[i] & 0xF]); + } + + // Write trailing '\n' + putch('\n'); +} diff --git a/pyecsca/codegen/simpleserial/simpleserial.h b/pyecsca/codegen/simpleserial/simpleserial.h new file mode 100644 index 0000000..fa64865 --- /dev/null +++ b/pyecsca/codegen/simpleserial/simpleserial.h @@ -0,0 +1,42 @@ +// simpleserial.h +// Generic module for interpreting SimpleSerial commands + +#ifndef SIMPLESERIAL_H +#define SIMPLESERIAL_H + +#include <stdint.h> + +// Set up the SimpleSerial module +// This prepares any internal commands +void simpleserial_init(void); + +// Add a command to the SimpleSerial module +// Args: +// - c: The character designating this command +// - len: The number of bytes expected +// - fp: A pointer to a callback, which is called after receiving data +// Example: simpleserial_addcmd('p', 16, encrypt_text) +// - Calls encrypt_text() with a 16 byte array after receiving a line +// like p00112233445566778899AABBCCDDEEFF\n +// Notes: +// - Maximum of 26 active commands +// - Maximum length of 256 bytes +// - Returns 1 if either of these fail; otherwise 0 +// - The callback function returns a number in [0x00, 0xFF] as a status code; +// in protocol v1.1, this status code is returned through a "z" message +int simpleserial_addcmd(char c, unsigned int len, uint8_t (*fp)(uint8_t*, uint16_t)); + +// Attempt to process a command +// If a full string is found, the relevant callback function is called +// Might return without calling a callback for several reasons: +// - First character didn't match any known commands +// - One of the characters wasn't in [0-9|A-F|a-f] +// - Data was too short or too long +void simpleserial_get(void); + +// Write some data to the serial port +// Prepends the character c to the start of the line +// Example: simpleserial_put('r', 16, ciphertext) +void simpleserial_put(char c, int size, uint8_t* output); + +#endif // SIMPLESERIAL_H |
