cAGE on-target decryption running

This commit is contained in:
jaseg 2021-07-14 12:49:51 +02:00
parent 4ae75202f4
commit 05c02ab7a7
14 changed files with 337 additions and 216 deletions

20
demo/fw/.gdbinit Normal file
View file

@ -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

View file

@ -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='<tb_mbedtls_config.h>'
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) > $@

View file

@ -1,189 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
* 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 <stdint.h>
/*
* 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 */

View file

@ -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;

View file

@ -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=="},

View file

@ -52,3 +52,6 @@ void DMA2_Stream7_IRQHandler(void) {
usart_dma_stream_irq(&con_usart);
}
void USART1_IRQHandler(void) {
usart_irq(&con_usart);
}

View file

@ -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

View file

@ -4,7 +4,7 @@
* Copyright (C) 2021 jaseg <code@jaseg.de>
*
*
* 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<<GPIO_MODER_MODER11_Pos) | (1<<GPIO_MODER_MODER12_Pos) | (1<<GPIO_MODER_MODER15_Pos);
#endif
con_printf("Running crypto startup test.\r\n");
rng_init();
ta_init(ta_heap, ta_heap+sizeof(ta_heap), 256, 16, 8);
/* Begin crypto test */
@ -250,21 +273,21 @@ int main(void)
enum ca_error err = ca_keystore_load_x25519_private_key(&ks, private_key);
assert (!err);
size_t bufsize = 16384;
char *buf = malloc(bufsize);
assert (buf);
size_t read_pos = 0;
buf[0] = '\0';
con_printf("Test private key loaded.\r\n");
unsigned char file_key[16];
err = parse_age_buf(&ks, buf, read_pos+1, file_key);
err = parse_age_buf(&ks, cage_startup_test_data, sizeof(cage_startup_test_data), file_key);
assert (!err);
unsigned char *decrypted = malloc(bufsize);
unsigned char *decrypted = malloc(sizeof(cage_startup_test_data));
assert (decrypted);
size_t decrypted_size = 0;
err = stream_decrypt(decrypted, bufsize, &decrypted_size, buf, read_pos, file_key);
err = stream_decrypt(decrypted, sizeof(cage_startup_test_data), &decrypted_size, cage_startup_test_data, sizeof(cage_startup_test_data)-1, file_key);
assert (!err);
assert (decrypted_size > 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");

111
demo/fw/src/rng.c Normal file
View file

@ -0,0 +1,111 @@
/*
* This file is part of the tachibana project
*
* Copyright (C) 2021 jaseg <code@jaseg.de>
*
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <stm32f407xx.h>
#include <mbedtls/ctr_drbg.h>
#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);
}

29
demo/fw/src/rng.h Normal file
View file

@ -0,0 +1,29 @@
/*
* This file is part of the tachibana project
*
* Copyright (C) 2021 jaseg <code@jaseg.de>
*
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __RNG_H__
#define __RNG_H__
extern void *g_drbg_ctx;
void rng_init(void);
#endif /* __RNG_H__ */

View file

@ -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; i<size; i++) {
int val = usart_read_char(us);
if (val < 0) {
return i;
}
buf[i] = us->rx_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; i<size; i++) {
int val;
do {
val = usart_read_char(us);
} while (val == -1);
if (val == sep) {
buf[i] = 0;
return i;
} else {
buf[i] = val;
}
}
return -1;
}
void usart_dma_stream_irq(volatile struct usart_desc *us) {
uint8_t iflags = dma_get_isr_and_clear(us->tx_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);
}

View file

@ -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__

View file

@ -4,7 +4,7 @@
* Copyright (C) 2021 jaseg <code@jaseg.de>
*
*
* 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))
;

View file

@ -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()