aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca/codegen/simpleserial
diff options
context:
space:
mode:
authorJ08nY2019-11-21 19:10:50 +0100
committerJ08nY2019-11-21 19:10:50 +0100
commitc8d0bff46001bd5636825c5b0bb4c896cb34a4e6 (patch)
tree2b3029c6ca37e56e86daa34069ab39da3b1a5400 /pyecsca/codegen/simpleserial
downloadpyecsca-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.simpleserial26
-rw-r--r--pyecsca/codegen/simpleserial/simpleserial.c150
-rw-r--r--pyecsca/codegen/simpleserial/simpleserial.h42
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