diff --git a/templates/uno/configure b/templates/uno/configure index 41b0d04..e2f7ac5 100755 --- a/templates/uno/configure +++ b/templates/uno/configure @@ -1,2 +1,3 @@ #!/bin/bash -mv *.c *.h src/ +mv *.c src/ +mv *.h include/ diff --git a/templates/uno/src/crypto_aead.h b/templates/uno/include/crypto_aead.h similarity index 84% rename from templates/uno/src/crypto_aead.h rename to templates/uno/include/crypto_aead.h index eafabff..651490c 100644 --- a/templates/uno/src/crypto_aead.h +++ b/templates/uno/include/crypto_aead.h @@ -1,3 +1,7 @@ +#ifdef __cplusplus +extern "C" { +#endif + int crypto_aead_encrypt( unsigned char *c,unsigned long long *clen, const unsigned char *m,unsigned long long mlen, @@ -17,3 +21,6 @@ int crypto_aead_decrypt( const unsigned char *k ); +#ifdef __cplusplus +} +#endif diff --git a/templates/uno/src/main.ino b/templates/uno/src/main.ino index 3a02edd..65cf370 100644 --- a/templates/uno/src/main.ino +++ b/templates/uno/src/main.ino @@ -1,40 +1,186 @@ #include "crypto_aead.h" #include "api.h" -/* - Blink +#define MAX_BYTES 100 - Turns an LED on for one second, then off for one second, repeatedly. +#define DEBUG - Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO - it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to - the correct LED pin independent of which board is used. - If you want to know what pin the on-board LED is connected to on your Arduino - model, check the Technical Specs of your board at: - https://www.arduino.cc/en/Main/Products +uint8_t npub[CRYPTO_NPUBBYTES]; +uint8_t nsec[CRYPTO_NSECBYTES]; +uint8_t k[CRYPTO_KEYBYTES]; +uint8_t ad[MAX_BYTES]; +unsigned long long int adlen; +uint8_t m[MAX_BYTES]; +unsigned long long int mlen; +uint8_t c[MAX_BYTES]; +unsigned long long int clen; - modified 8 May 2014 - by Scott Fitzgerald - modified 2 Sep 2016 - by Arturo Guadalupi - modified 8 Sep 2016 - by Colby Newman +void uart_write(uint8_t x) { + Serial.write((uint8_t) (x)); +} + +uint8_t uart_read() { + int r; + do { + r = Serial.read(); + } while (r == -1); + return (uint8_t) (0xff & r); +} + +// Simple serial protocol with packets and checksum +const uint8_t AMUX_TAG = 0xf9; +const uint8_t AMUX_END = 0xf3; +const uint8_t AMUX_EXT = 0x80; + +void uartp_send(const void *src, uint16_t len) { + uint8_t len_ind_0, len_ind_1, fcs, info; + const uint8_t *buf = (const uint8_t *) src; + + uart_write(AMUX_TAG); + len_ind_0 = (uint8_t) (0xff & len); + len_ind_1 = (uint8_t) (0xff & (len >> 7)); + if (len < 128) { + uart_write(len_ind_0); + } else { + uart_write(len_ind_0 | AMUX_EXT); + uart_write(len_ind_1); + } + fcs = 0; + for (uint16_t i = 0; i < len; i++) { + info = buf[i]; + fcs += info; + uart_write(buf[i]); + } + fcs = 255 - fcs; + uart_write(fcs); + uart_write(AMUX_END); +} + + +uint16_t uartp_recv(void *dst, uint16_t buf_len) { + uint8_t *buf = (uint8_t *) dst; + uint8_t tag_old, tag, info, cs; + uint16_t len; - This example code is in the public domain. + tag = AMUX_END; + while (1) { - http://www.arduino.cc/en/Tutorial/Blink -*/ + do { + tag_old = tag; + tag = uart_read(); + } while(tag != AMUX_TAG || tag_old != AMUX_END); + + len = (uint16_t) uart_read(); + if (len & AMUX_EXT) { + len &= (~AMUX_EXT); + len |= (uint16_t) (uart_read() << 7); + } + if (len > buf_len) { + return len; + } + + uint16_t i = 0; + cs = 0; + for (i = 0; i < len; i++) { + info = uart_read(); + buf[i] = info; + cs += info; + } + cs += uart_read(); + tag = uart_read(); + if (0xff == cs) { + if (AMUX_END == tag) { + return len; + } + } + + } +} + +#ifdef DEBUG +#define DEBUG_BUF_LEN 80 +int dbg_printf(const char *format, ...) { + char printbuf[DEBUG_BUF_LEN+2]; + + va_list vargs; + va_start(vargs, format); + int r = vsnprintf(printbuf+1, DEBUG_BUF_LEN, format, vargs); + va_end(vargs); + + if (r < 0) { + memcpy(printbuf+1, "DEBUG ERROR\r\n", 13); + r = 13; + } + + r = r > DEBUG_BUF_LEN ? DEBUG_BUF_LEN : r; + printbuf[0] = 0xde; // Debug messages should start with "\xde" + uartp_send(printbuf, r+1); + return r; +} +#else + #define dbg_printf(...) (0) +#endif + +void assert(bool b) { + if (b) + return; + dbg_printf("Assertion failed\r\n"); + for(;;) + yield(); +} -// the setup function runs once when you press reset or power the board void setup() { - // initialize digital pin LED_BUILTIN as an output. - pinMode(LED_BUILTIN, OUTPUT); + Serial.begin(115200); + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); + delay(100); + Serial.println("Hello, World!"); } -// the loop function runs over and over again forever + void loop() { - digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) - delay(1000); // wait for a second - digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW - delay(1000); // wait for a second + static uint8_t buf[256]; + int res; + uint16_t len = uartp_recv(buf, 255); + uint8_t action = buf[0]; + if (len == 0 || len > 255) + return; + + dbg_printf("Received command %c\r\n", action); + uint16_t l = len - 1; + uint8_t *var = buf+1; + switch (action) { + case 'm': assert(l <= MAX_BYTES); memcpy(m, var, l); mlen = l; break; + case 'c': assert(l <= MAX_BYTES); memcpy(c, var, l); clen = l; break; + case 'a': assert(l <= MAX_BYTES); memcpy(ad, var, l); adlen = l; break; + case 'k': assert(l == CRYPTO_KEYBYTES); memcpy(k, var, l); break; + case 'p': assert(l == CRYPTO_NPUBBYTES); memcpy(npub, var, l); break; + case 's': assert(l == CRYPTO_NSECBYTES); memcpy(nsec, var, l); break; + case 'e': + digitalWrite(LED_BUILTIN, LOW); + res = crypto_aead_encrypt(c, &clen, m, mlen, ad, adlen, nsec, npub, k); + digitalWrite(LED_BUILTIN, HIGH); + break; + case 'd': + digitalWrite(LED_BUILTIN, LOW); + res = crypto_aead_decrypt(m, &mlen, nsec, c, clen, ad, adlen, npub, k); + digitalWrite(LED_BUILTIN, HIGH); + break; + } + + switch (action) { + case'a': case'c': case'k': case'm': case'p': case's': + case'd': case'e': + l = 0; + break; + case'M': var = m; l = mlen; break; + case'C': var = c; l = clen; break; + case'A': var = ad; l = adlen; break; + case'K': var = k; l = CRYPTO_KEYBYTES; break; + case'P': var = npub; l = CRYPTO_NPUBBYTES; break; + case'S': var = nsec; l = CRYPTO_NSECBYTES; break; + } + buf[0] = action; + memcpy(buf+1, var, l); + uartp_send(buf, l+1); } diff --git a/templates/uno/test b/templates/uno/test index 09c90ac..de9197c 100755 --- a/templates/uno/test +++ b/templates/uno/test @@ -2,8 +2,13 @@ import os import sys +import struct +import serial import subprocess +def eprint(*args, **kargs): + print(*args, file=sys.stderr, **kargs) + def flash(): pipe = subprocess.PIPE @@ -11,13 +16,144 @@ def flash(): stdout=sys.stderr, stdin=pipe) stdout, stderr = p.communicate("") +def get_serial(): + import serial.tools.list_ports + ports = serial.tools.list_ports.comports() + devices = [ p.device for p in ports ] + devices.sort() + return devices[-1] + def main(argv): - print(argv[0], file=sys.stderr) + eprint(argv[0]) script_dir = os.path.split(argv[0])[0] if len(script_dir) > 0: os.chdir(script_dir) flash() - return 0; + + dev = get_serial() + ser = serial.Serial(dev, baudrate=115200, timeout=5) + + def uart_read(): + r = ser.read(1) + if len(r) != 1: + raise Exception("Serial read error") + return r[0] + + def uart_write(c): + b = struct.pack("B", c) + r = ser.write(b) + if r != len(b): + raise Exception("Serial write error") + return r + + def uart_recvframe(): + while 1: + tag_old = 0 + tag = 0xf3 + while tag_old != 0xf3 or tag != 0xf9: + tag_old = tag + tag = uart_read() + tag_old = tag + + l = uart_read() + if l & 0x80: + l &= 0x7f + l |= uart_read() << 7 + + fcs = 0 + buf = [] + for i in range(l): + info = uart_read() + buf.append(info) + fcs = (fcs + info) & 0xff + fcs = (fcs + uart_read()) & 0xff + + tag = uart_read() + if fcs == 0xff: + if tag == 0xf3: + buf = bytes(buf) + if len(buf) >= 1 and buf[0] == 0xde: + sys.stderr.buffer.write(buf[1:]) + sys.stderr.flush() + else: + return buf + + def uart_sendframe(buf): + uart_write(0xf9) + len_ind_0 = 0xff & len(buf) + len_ind_1 = 0xff & (len(buf) >> 7) + if len(buf) < 128: + uart_write(len_ind_0) + else: + uart_write(len_ind_0 | 0x80) + uart_write(len_ind_1) + fcs = 0 + for i in range(len(buf)): + info = buf[i] + fcs = (fcs + info) & 0xff + uart_write(buf[i]) + fcs = (0xff - fcs) & 0xff + uart_write(fcs) + uart_write(0xf3) + + def stdin_read(n): + b = sys.stdin.buffer.read(n) + if len(b) != n: + sys.exit(1) + return b + + def stdin_readvar(): + l = stdin_read(4) + (l, ) = struct.unpack("