From 32c851e393db7c7bdcf56a327f9a2f5f8f491ff3 Mon Sep 17 00:00:00 2001 From: Enrico Pozzobon Date: Thu, 18 Jul 2019 20:00:29 +0200 Subject: [PATCH] esp32 template (cheatinggit status) --- templates/esp32/.gitignore | 1 + templates/esp32/Makefile | 14 ++++++++++++++ templates/esp32/configure | 5 +++++ templates/esp32/include/crypto_aead.h | 26 ++++++++++++++++++++++++++ templates/esp32/include/uartp.h | 11 +++++++++++ templates/esp32/platformio.ini | 4 ++++ templates/esp32/src/main.ino | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ templates/esp32/src/uartp.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ templates/esp32/test | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 459 insertions(+) create mode 100644 templates/esp32/.gitignore create mode 100644 templates/esp32/Makefile create mode 100755 templates/esp32/configure create mode 100644 templates/esp32/include/crypto_aead.h create mode 100644 templates/esp32/include/uartp.h create mode 100644 templates/esp32/platformio.ini create mode 100644 templates/esp32/src/main.ino create mode 100644 templates/esp32/src/uartp.c create mode 100755 templates/esp32/test diff --git a/templates/esp32/.gitignore b/templates/esp32/.gitignore new file mode 100644 index 0000000..93ac46c --- /dev/null +++ b/templates/esp32/.gitignore @@ -0,0 +1 @@ +.pioenvs diff --git a/templates/esp32/Makefile b/templates/esp32/Makefile new file mode 100644 index 0000000..ffcef8e --- /dev/null +++ b/templates/esp32/Makefile @@ -0,0 +1,14 @@ +NISTGCCFLAGS=-std=c99 -Wall -Wextra -Wshadow -fsanitize=address,undefined -O2 +LFLAGS=-lm +all: esp32dev + +esp32dev: .pioenvs/esp32dev/firmware.hex + +.pioenvs/esp32dev/firmware.hex: FORCE + platformio run -e esp32dev + +FORCE: ; +.PHONY: clean + +clean: + -rm .pioenvs/uno/firmware.hex diff --git a/templates/esp32/configure b/templates/esp32/configure new file mode 100755 index 0000000..2b8a084 --- /dev/null +++ b/templates/esp32/configure @@ -0,0 +1,5 @@ +#!/bin/bash +mv -n *.c *.C *.s *.S src/ +mv -n *.inc *.h *.H include/ +sed -i src/encrypt.c -e "s/\(\s\)init(/\1_init(/g" +exit 0 diff --git a/templates/esp32/include/crypto_aead.h b/templates/esp32/include/crypto_aead.h new file mode 100644 index 0000000..651490c --- /dev/null +++ b/templates/esp32/include/crypto_aead.h @@ -0,0 +1,26 @@ +#ifdef __cplusplus +extern "C" { +#endif + +int crypto_aead_encrypt( + unsigned char *c,unsigned long long *clen, + const unsigned char *m,unsigned long long mlen, + const unsigned char *ad,unsigned long long adlen, + const unsigned char *nsec, + const unsigned char *npub, + const unsigned char *k + ); + + +int crypto_aead_decrypt( + unsigned char *m,unsigned long long *outputmlen, + unsigned char *nsec, + const unsigned char *c,unsigned long long clen, + const unsigned char *ad,unsigned long long adlen, + const unsigned char *npub, + const unsigned char *k + ); + +#ifdef __cplusplus +} +#endif diff --git a/templates/esp32/include/uartp.h b/templates/esp32/include/uartp.h new file mode 100644 index 0000000..3a80a60 --- /dev/null +++ b/templates/esp32/include/uartp.h @@ -0,0 +1,11 @@ +#pragma once +#ifdef __cplusplus +extern "C" { +#endif + +void uartp_send(const void *src, uint16_t len); +uint16_t uartp_recv(void *dst, uint16_t buf_len); + +#ifdef __cplusplus +} +#endif diff --git a/templates/esp32/platformio.ini b/templates/esp32/platformio.ini new file mode 100644 index 0000000..a495eb0 --- /dev/null +++ b/templates/esp32/platformio.ini @@ -0,0 +1,4 @@ +[env:esp32dev] +platform = espressif32 +framework = arduino +board = esp32dev diff --git a/templates/esp32/src/main.ino b/templates/esp32/src/main.ino new file mode 100644 index 0000000..d1181bf --- /dev/null +++ b/templates/esp32/src/main.ino @@ -0,0 +1,133 @@ +#include "crypto_aead.h" +#include "api.h" +#include "uartp.h" + +#define MAX_BYTES 100 + +//#define DEBUG +#define CRYPTO_BUSY 12 + +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; + +void setup(); +void loop(); + +#ifdef __cplusplus +extern "C" { +#endif + +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); +} + +#ifdef __cplusplus +} +#endif + +#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 my_assert(bool b) { + if (b) + return; + dbg_printf("Assertion failed\r\n"); + for(;;) + yield(); +} + +void setup() { + Serial.begin(115200); + pinMode(CRYPTO_BUSY, OUTPUT); + digitalWrite(CRYPTO_BUSY, HIGH); + delay(100); + Serial.print("Hello, World!"); +} + + +void loop() { + 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; + + uint16_t l = len - 1; + uint16_t rl = 0; + uint8_t *var = buf+1; + switch (action) { + case 'm': my_assert(l <= MAX_BYTES); memcpy(m, var, l); mlen = l; break; + case 'c': my_assert(l <= MAX_BYTES); memcpy(c, var, l); clen = l; break; + case 'a': my_assert(l <= MAX_BYTES); memcpy(ad, var, l); adlen = l; break; + case 'k': my_assert(l == CRYPTO_KEYBYTES); memcpy(k, var, l); break; + case 'p': my_assert(l == CRYPTO_NPUBBYTES); memcpy(npub, var, l); break; + case 's': my_assert(l == CRYPTO_NSECBYTES); memcpy(nsec, var, l); break; + case 'e': + noInterrupts(); + asm("nop"); + digitalWrite(CRYPTO_BUSY, LOW); + res = crypto_aead_encrypt(c, &clen, m, mlen, ad, adlen, nsec, npub, k); + digitalWrite(CRYPTO_BUSY, HIGH); + asm("nop"); + interrupts(); + break; + case 'd': + noInterrupts(); + asm("nop"); + digitalWrite(CRYPTO_BUSY, LOW); + res = crypto_aead_decrypt(m, &mlen, nsec, c, clen, ad, adlen, npub, k); + digitalWrite(CRYPTO_BUSY, HIGH); + asm("nop"); + interrupts(); + break; + case'M': var = m; rl = mlen; break; + case'C': var = c; rl = clen; break; + case'A': var = ad; rl = adlen; break; + case'K': var = k; rl = CRYPTO_KEYBYTES; break; + case'P': var = npub; rl = CRYPTO_NPUBBYTES; break; + case'S': var = nsec; rl = CRYPTO_NSECBYTES; break; + default: + dbg_printf("Unknown command\r\n"); + my_assert(false); + } + buf[0] = action; + memcpy(buf+1, var, rl); + uartp_send(buf, rl+1); +} diff --git a/templates/esp32/src/uartp.c b/templates/esp32/src/uartp.c new file mode 100644 index 0000000..62874d4 --- /dev/null +++ b/templates/esp32/src/uartp.c @@ -0,0 +1,76 @@ +#include +#include "uartp.h" + +extern void uart_write(uint8_t x); +extern uint8_t uart_read(); + +// 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; + + tag = AMUX_END; + while (1) { + + 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; + } + } + + } +} + diff --git a/templates/esp32/test b/templates/esp32/test new file mode 100755 index 0000000..6794930 --- /dev/null +++ b/templates/esp32/test @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 + +import os +import sys +import time +import struct +import serial +import subprocess + + + +def eprint(*args, **kargs): + print(*args, file=sys.stderr, **kargs) + + +def flash(tty=None): + pipe = subprocess.PIPE + cmd = ['platformio', 'run', '-e', 'esp32dev', '--target', 'upload'] + if tty is not None: + cmd.extend(['--upload-port', tty]) + p = subprocess.Popen(cmd, + 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] + + +class UARTP: + def __init__(self, ser): + UARTP.SYN = 0xf9 + UARTP.FIN = 0xf3 + self.ser = ser + + def uart_read(self): + r = self.ser.read(1) + if len(r) != 1: + raise Exception("Serial read error") + return r[0] + + def uart_write(self, c): + b = struct.pack("B", c) + r = self.ser.write(b) + if r != len(b): + raise Exception("Serial write error") + return r + + def send(self, buf): + self.uart_write(UARTP.SYN) + len_ind_0 = 0xff & len(buf) + len_ind_1 = 0xff & (len(buf) >> 7) + if len(buf) < 128: + self.uart_write(len_ind_0) + else: + self.uart_write(len_ind_0 | 0x80) + self.uart_write(len_ind_1) + fcs = 0 + for i in range(len(buf)): + info = buf[i] + fcs = (fcs + info) & 0xff + self.uart_write(buf[i]) + fcs = (0xff - fcs) & 0xff + self.uart_write(fcs) + self.uart_write(UARTP.FIN) + eprint("sent frame '%s'" % buf.hex()) + + def recv(self): + tag_old = UARTP.FIN + while 1: + tag = tag_old + while 1: + if tag_old == UARTP.FIN: + if tag == UARTP.SYN: + break + tag_old = tag + tag = self.uart_read() + tag_old = tag + + l = self.uart_read() + if l & 0x80: + l &= 0x7f + l |= self.uart_read() << 7 + + fcs = 0 + buf = [] + for i in range(l): + info = self.uart_read() + buf.append(info) + fcs = (fcs + info) & 0xff + fcs = (fcs + self.uart_read()) & 0xff + + tag = self.uart_read() + if fcs == 0xff: + if tag == UARTP.FIN: + buf = bytes(buf) + eprint("rcvd frame '%s'" % buf.hex()) + if len(buf) >= 1 and buf[0] == 0xde: + sys.stderr.buffer.write(buf[1:]) + sys.stderr.flush() + else: + return buf + +def main(argv): + eprint(argv[0]) + script_dir = os.path.split(argv[0])[0] + if len(script_dir) > 0: + os.chdir(script_dir) + + dev = get_serial() + flash(dev) + eprint("Flashed") + time.sleep(0.1) + + ser = serial.Serial(dev, baudrate=115200, timeout=5) + uartp = UARTP(ser) + + ser.setDTR(False) # IO0=HIGH + ser.setRTS(True) # EN=LOW, chip in reset + time.sleep(0.1) + ser.setDTR(False) # IO0=HIGH + ser.setRTS(False) # EN=HIGH, chip out of reset + time.sleep(1) + + 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("