From 05c02ab7a7fb09b19d7f455384c6abf13e37160a Mon Sep 17 00:00:00 2001 From: jaseg Date: Wed, 14 Jul 2021 12:49:51 +0200 Subject: [PATCH] cAGE on-target decryption running --- demo/fw/.gdbinit | 20 ++++ demo/fw/Makefile | 17 ++- demo/fw/include/endian.h | 189 --------------------------------- demo/fw/src/cage.c | 7 +- demo/fw/src/cage_base64.c | 2 - demo/fw/src/con_usart.c | 3 + demo/fw/src/con_usart.h | 1 + demo/fw/src/main.c | 51 +++++++-- demo/fw/src/rng.c | 111 +++++++++++++++++++ demo/fw/src/rng.h | 29 +++++ demo/fw/src/serial.c | 81 +++++++++++++- demo/fw/src/serial.h | 26 ++++- demo/fw/src/spi.c | 3 +- demo/fw/tools/bin_to_header.py | 13 +++ 14 files changed, 337 insertions(+), 216 deletions(-) create mode 100644 demo/fw/.gdbinit delete mode 100644 demo/fw/include/endian.h create mode 100644 demo/fw/src/rng.c create mode 100644 demo/fw/src/rng.h create mode 100644 demo/fw/tools/bin_to_header.py diff --git a/demo/fw/.gdbinit b/demo/fw/.gdbinit new file mode 100644 index 0000000..02e684d --- /dev/null +++ b/demo/fw/.gdbinit @@ -0,0 +1,20 @@ + +target remote localhost:3333 +set print pretty on +set print elements 512 + +# Update GDB's Python paths with the `sys.path` values of the local Python installation, +# whether that is brew'ed Python, a virtualenv, or another system python. + +# Convert GDB to interpret in Python +python +import os,subprocess,sys +# Execute a Python using the user's shell and pull out the sys.path (for site-packages) +paths = subprocess.check_output('python -c "import os,sys;print(os.linesep.join(sys.path).strip())"',shell=True).decode("utf-8").split() +# Extend GDB's Python's search path +sys.path.extend(paths) +end + +source ../../upstream/PyCortexMDebug/cmdebug/svd_gdb.py +svd_load ../../upstream/stm32square/svd/STM32F407.svd + diff --git a/demo/fw/Makefile b/demo/fw/Makefile index 355241f..7f3d5cf 100644 --- a/demo/fw/Makefile +++ b/demo/fw/Makefile @@ -19,6 +19,7 @@ C_SOURCES += src/serial.c C_SOURCES += src/spi.c C_SOURCES += src/gpio_helpers.c C_SOURCES += src/dma_util.c +C_SOURCES += src/rng.c C_SOURCES += src/cage.c C_SOURCES += src/cage_base64.c C_SOURCES += src/bech32.c @@ -62,7 +63,6 @@ SIZE := $(PREFIX)size NM := $(PREFIX)nm OBJCOPY := $(PREFIX)objcopy OBJDUMP := $(PREFIX)objdump -GDB := $(PREFIX)gdb HOST_CC ?= $(HOST_PREFIX)gcc HOST_CXX ?= $(HOST_PREFIX)g++ @@ -86,11 +86,11 @@ SYSTEM_FLAGS ?= -nostdlib -ffreestanding -nostartfiles #CFLAGS += -I$(abspath musl_include_shims) INCLUDES += -I$(CUBE_CMSIS_DIR)/Include -I$(CMSIS_DIR)/CMSIS/Core/Include -INCLUDES += -Itinyprintf -I$(MBEDTLS_DIR)/include -I$(TINYALLOC_DIR) +INCLUDES += -Itinyprintf -I$(TINYALLOC_DIR) -Iinclude/platform MBEDTLS_CONFIG_INCLUDE := -I$(realpath include) -DMBEDTLS_CONFIG_FILE='' -COMMON_INCLUDES += -I$(BUILDDIR) -Isrc $(MBEDTLS_CONFIG_INCLUDE) +COMMON_INCLUDES += -I$(BUILDDIR) -Isrc $(MBEDTLS_CONFIG_INCLUDE) -I$(MBEDTLS_DIR)/include -COMMON_CFLAGS += -O0 -std=gnu11 -g -DSTM32F407xx -DSTM32F4 -DDEBUG=$(DEBUG) -DMBEDTLS_ALLOW_PRIVATE_ACCESS +COMMON_CFLAGS += -O0 -std=gnu11 -g3 -DSTM32F407xx -DSTM32F4 -DDEBUG=$(DEBUG) -DMBEDTLS_ALLOW_PRIVATE_ACCESS CFLAGS += $(ARCH_FLAGS) $(SYSTEM_FLAGS) #SIM_CFLAGS += -mthumb -mcpu=cortex-m4 -mfloat-abi=soft CFLAGS += -fno-common -ffunction-sections -fdata-sections @@ -147,6 +147,15 @@ $(BUILDDIR)/libmbedcrypto.a: make -C $(MBEDTLS_DIR) CC=$(CC) LD=$(LD) CFLAGS="$(CFLAGS) $(COMMON_CFLAGS) $(MBEDTLS_CONFIG_INCLUDE) -w" LDFLAGS="$(LDFLAGS)" lib mv $(MBEDTLS_DIR)/library/libmbedcrypto.a $@ +$(BUILDDIR)/test/libmbedcrypto.a: + mkdir -p $(@D) + make -C $(MBEDTLS_DIR) clean + make -C $(MBEDTLS_DIR) CC=$(HOST_CC) LD=$(HOST_LD) CFLAGS="$(COMMON_CFLAGS) $(MBEDTLS_CONFIG_INCLUDE) -w" LDFLAGS="$(COMMON_LDFLAGS)" lib + mv $(MBEDTLS_DIR)/library/libmbedcrypto.a $@ + +build/test/cage_test: src/cage.c src/bech32.c src/cage_base64.c $(BUILDDIR)/test/libmbedcrypto.a + $(HOST_CC) $(COMMON_CFLAGS) $(COMMON_LDFLAGS) $(COMMON_INCLUDES) -DCAGE_DEBUG -o $@ $^ + build/$(BINARY:.elf=-symbol-sizes.dot): $(ALL_OBJS) $(BUILDDIR)/libmbedcrypto.a $(PYTHON3) tools/linkmem.py $(LINKMEM_FLAGS) $(LD) -T$(LDSCRIPT) $(LDFLAGS) $^ $(LIBS) > $@ diff --git a/demo/fw/include/endian.h b/demo/fw/include/endian.h deleted file mode 100644 index fa6379d..0000000 --- a/demo/fw/include/endian.h +++ /dev/null @@ -1,189 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2002 Thomas Moestl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ -/* - * Portions copyright (c) 2018, ARM Limited and Contributors. - * All rights reserved. - */ - -#ifndef ENDIAN_H -#define ENDIAN_H - -#include - -/* - * General byte order swapping functions. - */ -#define bswap16(x) __bswap16(x) -#define bswap32(x) __bswap32(x) -#define bswap64(x) __bswap64(x) - -/* - * Host to big endian, host to little endian, big endian to host, and little - * endian to host byte order functions as detailed in byteorder(9). - */ -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define htobe16(x) bswap16((x)) -#define htobe32(x) bswap32((x)) -#define htobe64(x) bswap64((x)) -#define htole16(x) ((uint16_t)(x)) -#define htole32(x) ((uint32_t)(x)) -#define htole64(x) ((uint64_t)(x)) - -#define be16toh(x) bswap16((x)) -#define be32toh(x) bswap32((x)) -#define be64toh(x) bswap64((x)) -#define le16toh(x) ((uint16_t)(x)) -#define le32toh(x) ((uint32_t)(x)) -#define le64toh(x) ((uint64_t)(x)) -#else /* __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ */ -#define htobe16(x) ((uint16_t)(x)) -#define htobe32(x) ((uint32_t)(x)) -#define htobe64(x) ((uint64_t)(x)) -#define htole16(x) bswap16((x)) -#define htole32(x) bswap32((x)) -#define htole64(x) bswap64((x)) - -#define be16toh(x) ((uint16_t)(x)) -#define be32toh(x) ((uint32_t)(x)) -#define be64toh(x) ((uint64_t)(x)) -#define le16toh(x) bswap16((x)) -#define le32toh(x) bswap32((x)) -#define le64toh(x) bswap64((x)) -#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ - -/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ - -static __inline uint16_t -be16dec(const void *pp) -{ - uint8_t const *p = (uint8_t const *)pp; - - return ((p[0] << 8) | p[1]); -} - -static __inline uint32_t -be32dec(const void *pp) -{ - uint8_t const *p = (uint8_t const *)pp; - - return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); -} - -static __inline uint64_t -be64dec(const void *pp) -{ - uint8_t const *p = (uint8_t const *)pp; - - return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); -} - -static __inline uint16_t -le16dec(const void *pp) -{ - uint8_t const *p = (uint8_t const *)pp; - - return ((p[1] << 8) | p[0]); -} - -static __inline uint32_t -le32dec(const void *pp) -{ - uint8_t const *p = (uint8_t const *)pp; - - return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); -} - -static __inline uint64_t -le64dec(const void *pp) -{ - uint8_t const *p = (uint8_t const *)pp; - - return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); -} - -static __inline void -be16enc(void *pp, uint16_t u) -{ - uint8_t *p = (uint8_t *)pp; - - p[0] = (u >> 8) & 0xff; - p[1] = u & 0xff; -} - -static __inline void -be32enc(void *pp, uint32_t u) -{ - uint8_t *p = (uint8_t *)pp; - - p[0] = (u >> 24) & 0xff; - p[1] = (u >> 16) & 0xff; - p[2] = (u >> 8) & 0xff; - p[3] = u & 0xff; -} - -static __inline void -be64enc(void *pp, uint64_t u) -{ - uint8_t *p = (uint8_t *)pp; - - be32enc(p, (uint32_t)(u >> 32)); - be32enc(p + 4, (uint32_t)(u & 0xffffffffU)); -} - -static __inline void -le16enc(void *pp, uint16_t u) -{ - uint8_t *p = (uint8_t *)pp; - - p[0] = u & 0xff; - p[1] = (u >> 8) & 0xff; -} - -static __inline void -le32enc(void *pp, uint32_t u) -{ - uint8_t *p = (uint8_t *)pp; - - p[0] = u & 0xff; - p[1] = (u >> 8) & 0xff; - p[2] = (u >> 16) & 0xff; - p[3] = (u >> 24) & 0xff; -} - -static __inline void -le64enc(void *pp, uint64_t u) -{ - uint8_t *p = (uint8_t *)pp; - - le32enc(p, (uint32_t)(u & 0xffffffffU)); - le32enc(p + 4, (uint32_t)(u >> 32)); -} - -#endif /* ENDIAN_H */ diff --git a/demo/fw/src/cage.c b/demo/fw/src/cage.c index 5befb91..66c057a 100644 --- a/demo/fw/src/cage.c +++ b/demo/fw/src/cage.c @@ -11,12 +11,13 @@ #include "cage_base64.h" #include "logging.h" #include "bech32.h" +#include "rng.h" #include "mbedtls/chachapoly.h" #include "mbedtls/md.h" #include "mbedtls/hkdf.h" #include "mbedtls/ecp.h" -#include "mbedtls/base64.h" +#include "mbedtls/ctr_drbg.h" static enum ca_error parse_stanza(struct ca_keystore *ks, const char *stanza_head, size_t len, unsigned char file_key[16]); @@ -46,7 +47,7 @@ enum ca_error ca_keystore_load_x25519_private_key(struct ca_keystore *ks, const /* Reconstruct public key from private key */ mbedtls_rc = mbedtls_ecp_mul(&(ks->x25519_kp.grp), &(ks->x25519_kp.Q), &(ks->x25519_kp.d), &(ks->x25519_kp.grp.G), - NULL, NULL/* FIXME: DEBUG ONLY!!! */); + mbedtls_ctr_drbg_random, g_drbg_ctx); if (mbedtls_rc) { LOG_PRINTF("Error: mbedtls_ecp_read_key: rc=-0x%x\n", -mbedtls_rc); return CA_ERR_MBEDTLS_ERROR; @@ -286,7 +287,7 @@ enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const ch mbedtls_ecp_point_init(&ecp_dec_res_pt); mbedtls_rc = mbedtls_ecp_mul(&x25519_grp, &ecp_dec_res_pt, &(ks->x25519_kp.d), &ecp_ciphertext_pt, - NULL, NULL/* FIXME: DEBUG ONLY!!! */); + mbedtls_ctr_drbg_random, g_drbg_ctx); if (mbedtls_rc) { LOG_PRINTF("Error: mbedtls_ecp_mul: rc=-0x%x\n", -mbedtls_rc); return CA_ERR_MBEDTLS_ERROR; diff --git a/demo/fw/src/cage_base64.c b/demo/fw/src/cage_base64.c index f3d0b21..7ba87d9 100644 --- a/demo/fw/src/cage_base64.c +++ b/demo/fw/src/cage_base64.c @@ -58,8 +58,6 @@ const char *base64_decode(unsigned char *dst, size_t dlen, size_t *olen, const c #ifdef CAGE_DEBUG -static void base64_decode_test(void); - static const char *base64_test_vectors[][2] = { {"", ""}, {"f", "Zg=="}, diff --git a/demo/fw/src/con_usart.c b/demo/fw/src/con_usart.c index 3fafe11..7bdc941 100644 --- a/demo/fw/src/con_usart.c +++ b/demo/fw/src/con_usart.c @@ -52,3 +52,6 @@ void DMA2_Stream7_IRQHandler(void) { usart_dma_stream_irq(&con_usart); } +void USART1_IRQHandler(void) { + usart_irq(&con_usart); +} diff --git a/demo/fw/src/con_usart.h b/demo/fw/src/con_usart.h index 181b6a6..d0d896d 100644 --- a/demo/fw/src/con_usart.h +++ b/demo/fw/src/con_usart.h @@ -28,6 +28,7 @@ extern volatile struct usart_desc con_usart; #define con_printf(...) usart_printf(&con_usart, __VA_ARGS__) #define con_printf_blocking(...) usart_printf_blocking(&con_usart, __VA_ARGS__) +#define con_read_until(...) usart_read_until(&con_usart, __VA_ARGS__) #ifndef CON_USART_BAUDRATE #define CON_USART_BAUDRATE 500000 diff --git a/demo/fw/src/main.c b/demo/fw/src/main.c index 8f17c2f..c5734f3 100644 --- a/demo/fw/src/main.c +++ b/demo/fw/src/main.c @@ -4,7 +4,7 @@ * Copyright (C) 2021 jaseg * * - * libusbhost is free software: you can redistribute it and/or modify + * tachibana is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. @@ -32,6 +32,7 @@ #include "jl_global.h" #include "con_usart.h" #include "spi.h" +#include "rng.h" #include "cage.h" #include "bech32.h" @@ -45,6 +46,25 @@ unsigned int apb2_timer_speed = 0; struct leds leds; struct spi_fpga_if spif; +uint8_t cage_startup_test_data[] = { + 0x61, 0x67, 0x65, 0x2d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6f, + 0x72, 0x67, 0x2f, 0x76, 0x31, 0x0a, 0x2d, 0x3e, 0x20, 0x58, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, + 0x35, 0x62, 0x6e, 0x32, 0x4d, 0x37, 0x65, 0x4d, 0x78, 0x49, 0x2b, 0x58, 0x4a, 0x30, 0x57, 0x52, + 0x57, 0x71, 0x2f, 0x35, 0x6c, 0x56, 0x34, 0x2f, 0x42, 0x67, 0x4c, 0x64, 0x2f, 0x52, 0x39, 0x34, + 0x70, 0x31, 0x58, 0x63, 0x51, 0x52, 0x73, 0x32, 0x42, 0x30, 0x41, 0x0a, 0x72, 0x39, 0x6e, 0x34, + 0x46, 0x35, 0x61, 0x6a, 0x33, 0x58, 0x74, 0x45, 0x35, 0x2f, 0x30, 0x57, 0x35, 0x5a, 0x68, 0x2b, + 0x55, 0x46, 0x6e, 0x6a, 0x32, 0x42, 0x53, 0x4b, 0x55, 0x30, 0x47, 0x4c, 0x77, 0x68, 0x31, 0x78, + 0x70, 0x75, 0x63, 0x4f, 0x68, 0x4d, 0x6f, 0x0a, 0x2d, 0x2d, 0x2d, 0x20, 0x4e, 0x78, 0x72, 0x43, + 0x6b, 0x35, 0x43, 0x35, 0x39, 0x4c, 0x6a, 0x67, 0x75, 0x2f, 0x71, 0x37, 0x47, 0x4d, 0x7a, 0x68, + 0x4c, 0x4f, 0x41, 0x66, 0x58, 0x6b, 0x51, 0x49, 0x62, 0x75, 0x50, 0x64, 0x69, 0x68, 0x61, 0x47, + 0x2f, 0x35, 0x72, 0x72, 0x53, 0x59, 0x77, 0x0a, 0x92, 0x6f, 0xde, 0x4d, 0x73, 0x8c, 0x40, 0xca, + 0xdb, 0xe8, 0xd1, 0x20, 0x78, 0x71, 0x9b, 0xd7, 0xb4, 0xdb, 0x70, 0x95, 0xec, 0xc5, 0x4a, 0xe1, + 0xb0, 0x85, 0x34, 0x9b, 0xac, 0xac, 0x8a, 0xd7, 0x4f, 0xe3, 0xd8, 0x63, 0x80, 0x60, 0xc7, 0xb6, + 0x24, 0xf5, 0x35, 0x9e, 0xc7, 0xaf, 0xd8, 0x4f, 0xc2, 0xa7, 0x5b, 0xab, 0x3e, 0x85, 0x60, 0x0f, + 0x91, 0x22, 0x5a, 0x5a, 0x9a, 0xf8, 0x37, 0x97, 0x0d, 0x63, 0x23, 0xa2, 0x6a, 0xc0, 0x8e, 0xb8, + 0x5d, 0x66, 0x00 +}; + void __libc_init_array(void) { /* we don't need this. */ } void __assert_func (unused_a const char *file, unused_a int line, unused_a const char *function, unused_a const char *expr) { asm volatile ("bkpt"); @@ -235,6 +255,9 @@ int main(void) GPIOA->MODER |= (1< 0 && decrypted_size < sizeof(cage_startup_test_data)); + decrypted[decrypted_size-1] = '\0'; + + con_printf("%s\r\n", decrypted); /* End crypto test */ con_printf("Booted.\r\n"); @@ -273,6 +296,14 @@ int main(void) int k = 0; con_printf("loop"); while (23) { + + uint8_t rd_buf[128]; + ssize_t rv = con_read_until(rd_buf, sizeof(rd_buf), '\n'); + if (rv < 0) { + con_printf("USART rx error\r\n"); + } + con_printf("Received %d bytes: %s\r\n", rv, rd_buf); + con_printf(" #%u", i); if (k == 0) spif_printf(&spif, "\33[1m"); @@ -290,7 +321,7 @@ int main(void) if (k == 0) { spif_printf(&spif, "\033[H\033[0m\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\033[H"); - uint8_t buf[128]; + uint8_t buf[4096]; spif_capture_read(&spif, sizeof(buf), buf); con_printf("\r\n"); con_printf("\r\n"); diff --git a/demo/fw/src/rng.c b/demo/fw/src/rng.c new file mode 100644 index 0000000..fe41216 --- /dev/null +++ b/demo/fw/src/rng.c @@ -0,0 +1,111 @@ +/* + * This file is part of the tachibana project + * + * Copyright (C) 2021 jaseg + * + * + * tachibana is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include "rng.h" + + +struct rng_state { + bool seed_error; + bool clock_error; + + size_t data_available; + uint32_t data[MBEDTLS_CTR_DRBG_ENTROPY_LEN]; +}; + +static volatile struct rng_state rng_state; +static mbedtls_ctr_drbg_context drbg_ctx; +void *g_drbg_ctx = &drbg_ctx; + +static int drbg_f_entropy(void *p, unsigned char *buf, size_t len); + + +int drbg_f_entropy(void *p, unsigned char *buf, size_t len) { + (void) p; + + if (rng_state.seed_error || rng_state.clock_error) { + return -2; + } + + if (len > sizeof(rng_state.data)/sizeof(rng_state.data[0])) { + return -1; + } + + NVIC_EnableIRQ(HASH_RNG_IRQn); + size_t it_max = 48000000; + while (len > rng_state.data_available * sizeof(rng_state.data[0])) { + /* wait for interrupt to fill buffer */ + if (--it_max == 0) { + return -3; + } + } + + memcpy(buf, (void *)rng_state.data, len); + rng_state.data_available = 0; + + return 0; +} + +void HASH_RNG_IRQHandler(void); +void HASH_RNG_IRQHandler() { + uint32_t sr = RNG->SR; + RNG->SR = 0; + + if (sr & RNG_SR_SEIS) { + rng_state.seed_error = true; + } + + if (sr & RNG_SR_CEIS) { + rng_state.clock_error = true; + } + + if (sr & RNG_SR_DRDY) { + rng_state.data[rng_state.data_available++] = RNG->DR; + if (rng_state.data_available >= sizeof(rng_state.data)/sizeof(rng_state.data[0])) { + NVIC_DisableIRQ(HASH_RNG_IRQn); + } + } +} + +void rng_init() { + rng_state.seed_error = false; + rng_state.clock_error = false; + rng_state.data_available = 0; + + RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN; + RNG->CR = RNG_CR_RNGEN | RNG_CR_IE; + + NVIC_EnableIRQ(HASH_RNG_IRQn); + NVIC_SetPriority(HASH_RNG_IRQn, 31); + + mbedtls_ctr_drbg_init(&drbg_ctx); + mbedtls_ctr_drbg_seed(&drbg_ctx, drbg_f_entropy, NULL, (const unsigned char *)UID_BASE, 12); +} + diff --git a/demo/fw/src/rng.h b/demo/fw/src/rng.h new file mode 100644 index 0000000..3ade7c0 --- /dev/null +++ b/demo/fw/src/rng.h @@ -0,0 +1,29 @@ +/* + * This file is part of the tachibana project + * + * Copyright (C) 2021 jaseg + * + * + * tachibana is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * + */ + +#ifndef __RNG_H__ +#define __RNG_H__ + +extern void *g_drbg_ctx; + +void rng_init(void); + +#endif /* __RNG_H__ */ diff --git a/demo/fw/src/serial.c b/demo/fw/src/serial.c index e9c79b1..ad7b5fa 100644 --- a/demo/fw/src/serial.c +++ b/demo/fw/src/serial.c @@ -49,6 +49,8 @@ void usart_dma_reset(volatile struct usart_desc *us) { void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate) { usart_dma_reset(us); + us->rx_buf.wr_pos = 0; + us->rx_buf.rd_pos = 0; /* Configure DMA 1 Channel 2 to handle uart transmission */ us->tx_dmas->PAR = (uint32_t)&(us->le_usart->DR); @@ -99,7 +101,7 @@ void usart_schedule_dma(volatile struct usart_desc *us) { } else { /* wraparound */ if (xfr_end != 0) buf->wraparound = true; - xfr_len = sizeof(us->data) - xfr_start; + xfr_len = sizeof(us->tx_data) - xfr_start; } } @@ -109,11 +111,81 @@ void usart_schedule_dma(volatile struct usart_desc *us) { us->comm_led = 100; /* initiate transmission of new buffer */ - us->tx_dmas->M0AR = (uint32_t)(us->data + xfr_start); + us->tx_dmas->M0AR = (uint32_t)(us->tx_data + xfr_start); us->tx_dmas->NDTR = xfr_len; us->tx_dmas->CR |= DMA_SxCR_EN; } +void usart_irq(volatile struct usart_desc *us) { + uint32_t sr = us->le_usart->SR; + uint8_t c = us->le_usart->DR; /* this read cleas all three flags below */ + + if (sr & USART_SR_RXNE) { + size_t new_wrpos = us->rx_buf.wr_pos + 1; + if (new_wrpos > sizeof(us->rx_data)) + new_wrpos = 0; + + if (new_wrpos != us->rx_buf.rd_pos) { + us->rx_data[us->rx_buf.wr_pos] = c; + us->rx_buf.wr_pos = new_wrpos; + + } else { + us->rx_buf_overruns ++; + } + } + + if (sr & USART_SR_FE) { + us->rx_framing_errors ++; + } + + if (sr & USART_SR_ORE) { + us->rx_overruns ++; + } +} + +int usart_read_char(volatile struct usart_desc *us) { + if (us->rx_buf.rd_pos != us->rx_buf.wr_pos) { + unsigned char data = us->rx_data[us->rx_buf.rd_pos]; + size_t new_rdpos = us->rx_buf.rd_pos + 1; + if (new_rdpos == sizeof(us->rx_data)) + new_rdpos = 0; + us->rx_buf.rd_pos = new_rdpos; + return data; + + } else { + return -1; + } +} + +ssize_t usart_read_nonblocking(volatile struct usart_desc *us, uint8_t *buf, size_t size) { + for (size_t i=0; irx_data[i]; + } + return size; +} + +ssize_t usart_read_until(volatile struct usart_desc *us, uint8_t *buf, size_t size, uint8_t sep) { + for (size_t i=0; itx_dma, us->tx_dma_sn); @@ -136,7 +208,7 @@ int usart_putc_nonblocking(volatile struct usart_desc *us, char c) { } buf->data[buf->wr_pos] = c; - buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data); + buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->tx_data); return 0; } @@ -147,7 +219,7 @@ int usart_putc_blocking(volatile struct usart_desc *us, char c) { ; buf->data[buf->wr_pos] = c; - buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data); + buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->tx_data); return 0; } @@ -205,3 +277,4 @@ int usart_printf_blocking(volatile struct usart_desc *us, const char *fmt, ...) return usart_printf_blocking_va(us, fmt, va); } + diff --git a/demo/fw/src/serial.h b/demo/fw/src/serial.h index 53eafb2..daba410 100644 --- a/demo/fw/src/serial.h +++ b/demo/fw/src/serial.h @@ -50,14 +50,29 @@ struct dma_tx_buf { #pragma GCC diagnostic pop }; +struct rx_buf { + size_t wr_pos; + size_t rd_pos; + +/* Make GCC shut up about the zero-size array member. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + uint8_t data[0]; +#pragma GCC diagnostic pop +}; + struct usart_desc { struct dma_tx_buf tx_buf; - uint8_t data[512]; + uint8_t tx_data[512]; + + volatile struct rx_buf rx_buf; + volatile uint8_t rx_data[512]; uint32_t tx_chunk_overruns, tx_byte_overruns; uint32_t tx_errors; - - volatile uint8_t rx_buf[32]; + uint32_t rx_framing_errors; + uint32_t rx_overruns; + uint32_t rx_buf_overruns; int comm_led; @@ -76,9 +91,14 @@ int usart_putc_nonblocking(volatile struct usart_desc *us, char c); int usart_putc_blocking(volatile struct usart_desc *us, char c); void usart_dma_stream_irq(volatile struct usart_desc *us); +void usart_irq(volatile struct usart_desc *us); int usart_flush(volatile struct usart_desc *us); int usart_printf(volatile struct usart_desc *us, const char *fmt, ...); int usart_printf_blocking(volatile struct usart_desc *us, const char *fmt, ...); int usart_printf_blocking_va(volatile struct usart_desc *us, const char *fmt, va_list va); +ssize_t usart_read_until(volatile struct usart_desc *us, uint8_t *buf, size_t size, uint8_t sep); +ssize_t usart_read_nonblocking(volatile struct usart_desc *us, uint8_t *buf, size_t size); +int usart_read_char(volatile struct usart_desc *us); + #endif // __SERIAL_H__ diff --git a/demo/fw/src/spi.c b/demo/fw/src/spi.c index d2f39e0..a7f936e 100644 --- a/demo/fw/src/spi.c +++ b/demo/fw/src/spi.c @@ -4,7 +4,7 @@ * Copyright (C) 2021 jaseg * * - * libusbhost is free software: you can redistribute it and/or modify + * tachibana is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. @@ -28,6 +28,7 @@ static uint8_t spi_read(struct spi_fpga_if *spif); static void spi_write(struct spi_fpga_if *spif, uint8_t b); static void spi_putc_blocking_tpf(void *spif, char c); + uint8_t spi_xfer(struct spi_fpga_if *spif, uint8_t b) { while (!(spif->spi->SR & SPI_SR_TXE)) ; diff --git a/demo/fw/tools/bin_to_header.py b/demo/fw/tools/bin_to_header.py new file mode 100644 index 0000000..af22086 --- /dev/null +++ b/demo/fw/tools/bin_to_header.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +import click +import sys + +@click.command() +def convert_to_c_header(): + data = sys.stdin.buffer.read() + + for i in range(0, len(data), 16): + print(', '.join(f'0x{c:02x}' for c in data[i:i+16]) + ',') + +if __name__ == '__main__': + convert_to_c_header()