[Cryptech-Commits] [user/ft/stm32-avalanche-noise] branch master updated: add RNG using ChaCha20 as CSPRNG

git at cryptech.is git at cryptech.is
Mon Nov 21 13:15:11 UTC 2016


This is an automated email from the git hooks/post-receive script.

fredrik at thulin.net pushed a commit to branch master
in repository user/ft/stm32-avalanche-noise.

The following commit(s) were added to refs/heads/master by this push:
     new e7f5fde  add RNG using ChaCha20 as CSPRNG
e7f5fde is described below

commit e7f5fdebef90d0be01edeabd4ea260138ed1fbd0
Author: Fredrik Thulin <fredrik at thulin.net>
AuthorDate: Mon Nov 21 11:45:58 2016 +0100

    add RNG using ChaCha20 as CSPRNG
---
 Makefile                        |   2 +-
 common.mk                       |   3 +-
 src/cc20rng/Makefile            |  56 +++++++
 src/cc20rng/cc20_prng.c         | 219 ++++++++++++++++++++++++
 src/cc20rng/cc20_prng.h         |  18 ++
 src/cc20rng/main.c              | 358 ++++++++++++++++++++++++++++++++++++++++
 src/cc20rng/main.h              |   4 +
 src/cc20rng/stm32f4xx_hal_msp.c | 113 +++++++++++++
 src/cc20rng/stm32f4xx_it.c      | 208 +++++++++++++++++++++++
 src/cc20rng/stm32f4xx_it.h      |  70 ++++++++
 src/cc20rng/stm_init.c          | 290 ++++++++++++++++++++++++++++++++
 src/cc20rng/stm_init.h          |  18 ++
 src/cc20rng/system_stm32f4xx.c  | 270 ++++++++++++++++++++++++++++++
 src/cc20rng/test.c              |  10 ++
 14 files changed, 1637 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 134ab13..1e6dfcf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-APPLICATION	= entropy
+APPLICATION	= cc20rng
 SRCDIR  	= src/$(APPLICATION)
 
 all: target
diff --git a/common.mk b/common.mk
index d9b981b..9006feb 100644
--- a/common.mk
+++ b/common.mk
@@ -31,6 +31,7 @@ OPENOCD_BOARD_DIR ?= /usr/share/openocd/scripts/board
 # the OPENOCD_BOARD_DIR directory.
 #
 OPENOCD_PROC_FILE ?= stm32f4discovery.cfg
+#OPENOCD_PROC_FILE ?= st_nucleo_f4.cfg
 
 # MCU selection parameters
 #
@@ -61,7 +62,7 @@ SIZE=arm-none-eabi-size
 GDB=arm-none-eabi-gdb
 OPENOCD=openocd
 
-CFLAGS  = -ggdb -O2 -Wall -Wextra -Warray-bounds
+CFLAGS  = -ggdb -O1 -Wall -Wextra -Warray-bounds
 CFLAGS += -mcpu=cortex-m4 -mthumb -mlittle-endian -mthumb-interwork
 CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
 CFLAGS += $(STDPERIPH_SETTINGS)
diff --git a/src/cc20rng/Makefile b/src/cc20rng/Makefile
new file mode 100644
index 0000000..2873505
--- /dev/null
+++ b/src/cc20rng/Makefile
@@ -0,0 +1,56 @@
+# put your *.o targets here, make should handle the rest!
+SRCS = main.c stm_init.c system_stm32f4xx.c stm32f4xx_it.c stm32f4xx_hal_msp.c cc20_prng.c
+
+# all the files will be generated with this name
+PROJ_NAME=cc20rng
+
+TOPLEVEL=../..
+include $(TOPLEVEL)/common.mk
+
+
+OBJS = $(SRCS:.c=.o)
+
+###################################################
+
+.PHONY: lib proj
+
+all: lib proj
+
+lib:
+	$(MAKE) -C $(STD_PERIPH_LIB) STDPERIPH_SETTINGS="$(STDPERIPH_SETTINGS)"
+
+
+proj: 	$(PROJ_NAME).elf
+
+$(PROJ_NAME).elf: $(SRCS)
+	$(CC) $(CFLAGS) $^ -o $@ -L$(STD_PERIPH_LIB) -lstmf4 -L$(LDSCRIPT_INC) -T$(MCU_LINKSCRIPT) -g
+	$(OBJCOPY) -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex
+	$(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin
+	$(OBJDUMP) -St $(PROJ_NAME).elf >$(PROJ_NAME).lst
+	$(SIZE) $(PROJ_NAME).elf
+
+clean:
+	find ./ -name '*~' | xargs rm -f
+	rm -f *.o
+	rm -f $(PROJ_NAME).elf
+	rm -f $(PROJ_NAME).hex
+	rm -f $(PROJ_NAME).bin
+	rm -f $(PROJ_NAME).map
+	rm -f $(PROJ_NAME).lst
+
+really-clean: clean
+	$(MAKE) -C $(STD_PERIPH_LIB) clean
+
+debug:
+    $(GDB) -ex "target remote localhost:3333" \
+        -ex "set remote hardware-breakpoint-limit 6" \
+        -ex "set remote hardware-watchpoint-limit 4" $(PROJ_NAME).elf
+
+flash-target:
+	$(OPENOCD) -f $(OPENOCD_BOARD_DIR)/$(OPENOCD_PROC_FILE) \
+		-c "program $(PROJ_NAME).elf verify" -c "reset"
+
+# test program not using cross compiling
+test: clean test.c cc20_prng.c
+	cc -DCHACHA20_PRNG_DEBUG -O2 -g -o test test.c cc20_prng.c
+	./test
diff --git a/src/cc20rng/cc20_prng.c b/src/cc20rng/cc20_prng.c
new file mode 100644
index 0000000..3d52fc6
--- /dev/null
+++ b/src/cc20rng/cc20_prng.c
@@ -0,0 +1,219 @@
+/*
+ * Simple implementation of chacha20 used as a CSPRNG.
+ *
+ * Copyright (c) 2016 NORDUnet A/S
+ * 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.
+ *    3. Neither the name of the NORDUnet nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDER 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.
+ */
+
+#include "cc20_prng.h"
+
+/* "expand 32-byte k" */
+#define CHACHA20_CONSTANT0 0x61707865
+#define CHACHA20_CONSTANT1 0x3320646e
+#define CHACHA20_CONSTANT2 0x79622d32
+#define CHACHA20_CONSTANT3 0x6b206574
+
+#ifdef CHACHA20_PRNG_DEBUG
+void _dump(struct cc20_state *cc, char *str);
+#endif
+
+inline uint32_t rotl32 (uint32_t x, uint32_t n)
+{
+    return (x << n) | (x >> (32 - n));
+}
+
+inline void _qr(struct cc20_state *cc, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
+{
+    cc->i[a] += cc->i[b];
+    cc->i[d] ^= cc->i[a];
+    cc->i[d] = rotl32(cc->i[d], 16);
+
+    cc->i[c] += cc->i[d];
+    cc->i[b] ^= cc->i[c];
+    cc->i[b] = rotl32(cc->i[b], 12);
+
+    cc->i[a] += cc->i[b];
+    cc->i[d] ^= cc->i[a];
+    cc->i[d] = rotl32(cc->i[d], 8);
+
+    cc->i[c] += cc->i[d];
+    cc->i[b] ^= cc->i[c];
+    cc->i[b] = rotl32(cc->i[b], 7);
+}
+
+void chacha20_prng_reseed(struct cc20_state *cc, uint32_t *entropy)
+{
+    uint32_t i = 256 / 8 / 4;
+    while (i--) {
+	cc->i[i] = entropy[i];
+    }
+}
+
+void chacha20_prng_block(struct cc20_state *cc, uint32_t block_counter, struct cc20_state *out)
+{
+    uint32_t i;
+
+    out->i[0] = CHACHA20_CONSTANT0;
+    out->i[1] = CHACHA20_CONSTANT1;
+    out->i[2] = CHACHA20_CONSTANT2;
+    out->i[3] = CHACHA20_CONSTANT3;
+
+    cc->i[12] = block_counter;
+
+    for (i = 4; i < CHACHA20_NUM_WORDS; i++) {
+	out->i[i] = cc->i[i];
+    }
+
+    for (i = 10; i; i--) {
+	_qr(out, 0, 4, 8,12);
+	_qr(out, 1, 5, 9,13);
+	_qr(out, 2, 6,10,14);
+	_qr(out, 3, 7,11,15);
+	_qr(out, 0, 5,10,15);
+	_qr(out, 1, 6,11,12);
+	_qr(out, 2, 7, 8,13);
+	_qr(out, 3, 4, 9,14);
+    }
+
+    for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+	out->i[i] += cc->i[i];
+    }
+}
+
+int chacha20_prng_self_test1()
+{
+    /* Test vector from RFC7539, section 2.3.2.
+     *   https://tools.ietf.org/html/rfc7539#section-2.3.2
+     */
+    struct cc20_state test = {
+        {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
+         0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
+         0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
+         0x00000001, 0x09000000, 0x4a000000, 0x00000000,
+        }};
+    struct cc20_state expected = {
+	{0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3,
+	 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3,
+	 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9,
+	 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2,
+	}};
+    uint32_t i;
+    struct cc20_state out;
+
+#ifdef CHACHA20_PRNG_DEBUG
+    _dump(&test, "Test vector from RFC7539, section 2.3.2. Input:");
+#endif
+
+    chacha20_prng_block(&test, 1, &out);
+#ifdef CHACHA20_PRNG_DEBUG
+    _dump(&out, "Test vector from RFC7539, section 2.3.2. Output:");
+#endif
+
+    for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+        if (out.i[i] != expected.i[i]) return 0;
+    }
+
+    return 1;
+}
+
+int chacha20_prng_self_test2()
+{
+    /* Two-block test vector from RFC7539, section 2.4.2.
+     *   https://tools.ietf.org/html/rfc7539#section-2.4.2
+     */
+    struct cc20_state test = {
+	{0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
+	 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
+	 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
+	 0x00000001, 0x00000000, 0x4a000000, 0x00000000,
+	}};
+    struct cc20_state expected1 = {
+	{0xf3514f22, 0xe1d91b40, 0x6f27de2f, 0xed1d63b8,
+	 0x821f138c, 0xe2062c3d, 0xecca4f7e, 0x78cff39e,
+	 0xa30a3b8a, 0x920a6072, 0xcd7479b5, 0x34932bed,
+	 0x40ba4c79, 0xcd343ec6, 0x4c2c21ea, 0xb7417df0,
+	}};
+    struct cc20_state expected2 = {
+	{0x9f74a669, 0x410f633f, 0x28feca22, 0x7ec44dec,
+	 0x6d34d426, 0x738cb970, 0x3ac5e9f3, 0x45590cc4,
+	 0xda6e8b39, 0x892c831a, 0xcdea67c1, 0x2b7e1d90,
+	 0x037463f3, 0xa11a2073, 0xe8bcfb88, 0xedc49139,
+	}};
+    struct cc20_state out;
+    uint32_t i;
+
+#ifdef CHACHA20_PRNG_DEBUG
+    _dump(&test, "Test vector from RFC7539, section 2.4.2. Input:");
+#endif
+
+    chacha20_prng_block(&test, 1, &out);
+#ifdef CHACHA20_PRNG_DEBUG
+    _dump(&out, "First block");
+#endif
+    for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+	if (out.i[i] != expected1.i[i]) return 0;
+    }
+
+    chacha20_prng_block(&test, 2, &out);
+#ifdef CHACHA20_PRNG_DEBUG
+    _dump(&out, "Second block");
+#endif
+    for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+	if (out.i[i] != expected2.i[i]) return 0;
+    }
+
+    return 1;
+}
+
+#ifdef CHACHA20_PRNG_DEBUG
+#include <stdio.h>
+void _dump(struct cc20_state *cc, char *str)
+{
+    uint32_t i;
+
+    printf("%s\n", str);
+
+    for (i = 0; i < 4; i++) {
+	printf("%02i  %08x %08x %08x %08x\n", i * 4, cc->i[i * 4 + 0],
+	       cc->i[i * 4 + 1], cc->i[i * 4 + 2], cc->i[i * 4 + 3]);
+    }
+    printf("\n");
+}
+#endif
+
+/* Test vector from RFC, used as simple power-on self-test of ability to compute
+ * a block correctly.
+ */
+int chacha20_prng_self_test()
+{
+    return \
+	chacha20_prng_self_test1() && \
+	chacha20_prng_self_test2();
+}
diff --git a/src/cc20rng/cc20_prng.h b/src/cc20rng/cc20_prng.h
new file mode 100644
index 0000000..6940f53
--- /dev/null
+++ b/src/cc20rng/cc20_prng.h
@@ -0,0 +1,18 @@
+#ifndef __STM32_CHACHA20_H
+#define __STM32_CHACHA20_H
+
+#include <stdint.h>
+
+#define CHACHA20_MAX_BLOCK_COUNTER	0xffffffff
+#define CHACHA20_NUM_WORDS              16
+#define CHACHA20_BLOCK_SIZE		(CHACHA20_NUM_WORDS * 4)
+
+struct cc20_state {
+    uint32_t i[CHACHA20_NUM_WORDS];
+};
+
+extern void chacha20_prng_reseed(struct cc20_state *cc, uint32_t *entropy);
+extern void chacha20_prng_block(struct cc20_state *cc, uint32_t block_counter, struct cc20_state *out);
+extern int chacha20_prng_self_test();
+
+#endif /* __STM32_CHACHA20_H */
diff --git a/src/cc20rng/main.c b/src/cc20rng/main.c
new file mode 100644
index 0000000..2c2650c
--- /dev/null
+++ b/src/cc20rng/main.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2014, 2015, 2016 NORDUnet A/S
+ * 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.
+ *    3. Neither the name of the NORDUnet nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDER 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.
+ */
+#include <string.h>
+
+#include "main.h"
+#include "stm_init.h"
+#include "cc20_prng.h"
+
+#define UART_RANDOM_BYTES_PER_CHUNK	8
+#define RESEED_BLOCKS			CHACHA20_MAX_BLOCK_COUNTER
+
+extern DMA_HandleTypeDef hdma_tim;
+
+UART_HandleTypeDef *huart;
+__IO ITStatus UartReady = RESET;
+
+static union {
+  uint8_t rnd[257];		/* 256 bytes + 1 for use in the POST */
+  uint32_t rnd32[64];
+} buf;
+
+/* First DMA value (DMA_counters[0]) is unreliable, leftover in DMA FIFO perhaps? */
+#define FIRST_DMA_IDX_USED  3
+
+/*
+ * Number of counters used to produce 8 bits of entropy is:
+ *   8 * 4 - four flanks are used to produce two (hopefully) uncorrelated bits (a and b)
+ *     * 2 - von Neumann will on average discard 1/2 of the bits 'a' and 'b'
+ */
+#define DMA_COUNTERS_NUM ((UART_RANDOM_BYTES_PER_CHUNK * 8 * 4 * 2) + FIRST_DMA_IDX_USED + 1)
+struct DMA_params {
+  volatile uint32_t buf0[DMA_COUNTERS_NUM];
+  volatile uint32_t buf1[DMA_COUNTERS_NUM];
+  volatile uint32_t write_buf;
+};
+
+static struct DMA_params DMA = {
+  {},
+  {},
+  0,
+};
+
+
+/* The main work horse functions */
+void get_entropy32(uint32_t num_bytes, uint32_t buf_idx);
+/* Various support functions */
+inline uint32_t get_one_bit(void) __attribute__((__always_inline__));
+volatile uint32_t *restart_DMA(void);
+inline volatile uint32_t *get_DMA_read_buf(void);
+inline uint32_t safe_get_counter(volatile uint32_t *dmabuf, const uint32_t dmabuf_idx);
+void check_uart_rx(UART_HandleTypeDef *this);
+void Error_Handler(void);
+void cc_reseed(struct cc20_state *cc);
+
+
+int
+main()
+{
+  uint32_t i, timeout, block_counter = 0;
+  struct cc20_state cc, out;
+  HAL_StatusTypeDef res;
+
+  /* Initialize buffers */
+  memset(buf.rnd, 0, sizeof(buf.rnd));
+  for (i = 0; i < DMA_COUNTERS_NUM; i++) {
+    DMA.buf0[i] = 0xffff0000 + i;
+    DMA.buf1[i] = 0xffff0100 + i;
+  }
+
+  stm_init((uint32_t *) &DMA.buf0, DMA_COUNTERS_NUM);
+
+  if (! chacha20_prng_self_test()) {
+      Error_Handler();
+  }
+
+  /* Ensure there is actual Timer IC counters in both DMA buffers. */
+  restart_DMA();
+  restart_DMA();
+
+  huart = &huart1;
+
+  /* Toggle GREEN LED to show we've initialized */
+  {
+    for (i = 0; i < 10; i++) {
+      HAL_GPIO_TogglePin(LED_PORT, LED_GREEN);
+      HAL_Delay(125);
+    }
+  }
+
+  /* Generate initial block of random data directly into buf */
+  cc_reseed(&cc);
+  block_counter = RESEED_BLOCKS;
+  chacha20_prng_block(&cc, block_counter--, (struct cc20_state *) buf.rnd32);
+
+  /*
+   * Main loop
+   */
+  while (1) {
+    if (! (block_counter % 1000)) {
+      HAL_GPIO_TogglePin(LED_PORT, LED_YELLOW);
+    }
+
+    if (! block_counter) {
+	cc_reseed(&cc);
+	block_counter = RESEED_BLOCKS;
+    }
+
+    /* Send buf on UART (non blocking interrupt driven send). */
+    UartReady = RESET;
+    res = HAL_UART_Transmit_IT(huart, &buf.rnd[0], CHACHA20_BLOCK_SIZE);
+
+    /* Generate next block while this block is being transmitted */
+    chacha20_prng_block(&cc, block_counter--, &out);
+    /* Copying using a loop is faster than memcpy on STM32 */
+    for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+	buf.rnd32[i] = out.i[i];
+    }
+
+    if (res == HAL_OK) {
+      timeout = 0xffff;
+      while (UartReady != SET && timeout) { timeout--; }
+    }
+
+    if (UartReady != SET) {
+      /* Failed to send, turn on RED LED for one second */
+      HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+      HAL_Delay(1000);
+      HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_RESET);
+    }
+
+    /* Check for UART change request */
+    check_uart_rx(&huart1);
+    check_uart_rx(&huart2);
+  }
+}
+
+
+/**
+ * @brief  Reseed chacha20 state with hardware generated entropy.
+ * @param  cc: ChaCha20 state
+ * @retval None
+ */
+void
+cc_reseed(struct cc20_state *cc)
+{
+    HAL_GPIO_WritePin(LED_PORT, LED_BLUE, GPIO_PIN_SET);
+
+    get_entropy32(CHACHA20_BLOCK_SIZE / 4, 0);
+    restart_DMA();
+    chacha20_prng_reseed(cc, (uint32_t *) &buf);
+
+    HAL_GPIO_WritePin(LED_PORT, LED_BLUE, GPIO_PIN_RESET);
+}
+
+/**
+ * @brief  Collect `count' times 32 bits of entropy.
+ * @param  count: Number of 32 bit words to collect.
+ * @param  start: Start index value into buf.rnd32.
+ * @retval None
+ */
+inline void get_entropy32(uint32_t count, const uint32_t start)
+{
+  uint32_t i, bits, buf_idx;
+
+  buf_idx = start;
+
+  do {
+    bits = 0;
+    /* Get 32 bits of entropy.
+     */
+    for (i = 32; i; i--) {
+      bits <<= 1;
+      bits += get_one_bit();
+    }
+
+    /* Store the 32 bits in output buffer */
+    buf.rnd32[buf_idx++] = bits;
+  } while (--count);
+}
+
+/**
+ * @brief  Return one bit of entropy.
+ * @param  None
+ * @retval One bit, in the LSB of an uint32_t since this is a 32 bit MCU.
+ */
+inline uint32_t get_one_bit()
+{
+  register uint32_t a, b, temp;
+  /* Start at end of buffer so restart_DMA() is called. */
+  static uint32_t dmabuf_idx = DMA_COUNTERS_NUM - 1;
+  volatile uint32_t *dmabuf;
+
+  dmabuf = get_DMA_read_buf();
+
+  do {
+    if (dmabuf_idx > DMA_COUNTERS_NUM - 1 - 4) {
+      /* If there are less than four counters available in the dmabuf,
+       * we need to get a fresh DMA buffer first.
+       */
+      dmabuf = restart_DMA();
+      dmabuf_idx = FIRST_DMA_IDX_USED;
+    }
+
+    /* Get one bit from two subsequent counter values */
+    a = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+    temp = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+    a ^= temp;
+
+    /* Get another bit from two other counter values. Getting
+     * two bits from two unrelated [1] pairs of counters is
+     * supposed to help against phase correlations between the
+     * frequency of the noise and the MCU sampling rate.
+     *
+     * [1] This is how it is done in the ARRGH board, although
+     *     since this is a faster MCU and DMA is used the two
+     *     pairs are more likely to still be related since they
+     *     are more likely to be directly subsequent diode
+     *     breakdowns. Have to evaluate if this is enough.
+     */
+    b = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+    temp = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+    b ^= temp;
+
+    /* Do von Neumann extraction of a and b to eliminate bias
+     * (only eliminates bias if a and b are uncorrelated)
+     */
+  } while (a == b);
+
+  return a;
+}
+
+/**
+ * @brief  Return a pointer to the DMA.buf NOT currently being written to
+ * @param  None
+ * @retval Pointer to buffer currently being read from.
+ */
+inline volatile uint32_t *get_DMA_read_buf(void)
+{
+  return DMA.write_buf ? DMA.buf0 : DMA.buf1;
+}
+
+/**
+ * @brief  Return a pointer to the DMA.buf currently being written to
+ * @param  None
+ * @retval Pointer to buffer currently being written to.
+ */
+inline volatile uint32_t *get_DMA_write_buf(void)
+{
+  return DMA.write_buf ? DMA.buf1 : DMA.buf0;
+}
+
+/**
+ * @brief  Initiate DMA collection of another buffer of Timer IC values.
+ * @param  None
+ * @retval Pointer to buffer full of Timer IC values ready to be consumed.
+ */
+volatile uint32_t *restart_DMA(void)
+{
+  /* Wait for transfer complete flag to become SET. Trying to change the
+   * M0AR register while the DMA is running is a no-no.
+   */
+  while(__HAL_DMA_GET_FLAG(&hdma_tim, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_tim)) == RESET) { ; }
+
+  /* Switch buffer being written to */
+  DMA.write_buf ^= 1;
+  hdma_tim.Instance->M0AR = (uint32_t) get_DMA_write_buf();
+
+  /* Start at 0 to help manual inspection */
+  TIM2->CNT = 0;
+
+  /* Clear the transfer complete flag before re-enabling DMA */
+  __HAL_DMA_CLEAR_FLAG(&hdma_tim, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_tim));
+  __HAL_DMA_ENABLE(&hdma_tim);
+
+  return get_DMA_read_buf();
+}
+
+/**
+ * @brief  Get one counter value, guaranteed to not have been used before.
+ * @param  dmabuf:     Pointer to the current DMA read buffer.
+ * @param  dmabuf_idx: Word index into `dmabuf'.
+ * @retval One Timer IC counter value.
+ */
+inline uint32_t safe_get_counter(volatile uint32_t *dmabuf, const uint32_t dmabuf_idx) {
+  register uint32_t a;
+  /* Prevent re-use of values. DMA stored values are <= 0xffff. */
+  do {
+    a = dmabuf[dmabuf_idx];
+  } while (a > 0xffff);
+  dmabuf[dmabuf_idx] = 0xffff0000;
+  return a;
+}
+
+/* UART transmit complete callback */
+void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UH)
+{
+  if ((UH->Instance == USART1 && huart->Instance == USART1) ||
+      (UH->Instance == USART2 && huart->Instance == USART2)) {
+    /* Signal UART transmit complete to the code in the main loop. */
+    UartReady = SET;
+  }
+}
+
+/*
+ * If a newline is received on UART1 or UART2, redirect output to that UART.
+ */
+void check_uart_rx(UART_HandleTypeDef *this) {
+  uint8_t rx = 0;
+  if (HAL_UART_Receive(this, &rx, 1, 0) == HAL_OK) {
+    if (rx == '\n') {
+      huart = this;
+      /* Signal UART transmit complete to the code in the main loop. */
+      UartReady = SET;
+    }
+  }
+}
+
+/**
+ * @brief  This function is executed in case of error occurrence.
+ * @param  None
+ * @retval None
+ */
+
+void Error_Handler(void)
+{
+  /* Turn on RED LED and then loop indefinitely */
+  HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+  while(1) { ; }
+}
diff --git a/src/cc20rng/main.h b/src/cc20rng/main.h
new file mode 100644
index 0000000..902ecf4
--- /dev/null
+++ b/src/cc20rng/main.h
@@ -0,0 +1,4 @@
+#ifndef __MAIN_H
+#define __MAIN_H
+
+#endif /* __MAIN_H */
diff --git a/src/cc20rng/stm32f4xx_hal_msp.c b/src/cc20rng/stm32f4xx_hal_msp.c
new file mode 100644
index 0000000..536a78c
--- /dev/null
+++ b/src/cc20rng/stm32f4xx_hal_msp.c
@@ -0,0 +1,113 @@
+#include "stm_init.h"
+#include "stm32f4xx_hal.h"
+
+static void Error_Handler(void);
+extern void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma);
+
+void HAL_TIM_IC_MspInit(TIM_HandleTypeDef* htim)
+{
+  if (htim->Instance == TIM2) {
+    /* Configure DMA input capturing.
+     *
+     * Amplified avalanche noise is present at pin PA1,
+     * which has Alternate Function TIM2_CH2.
+     *
+     * TIM2_CH2 is DMA1 stream 6, channel 3 according to Table 28
+     * (DMA1 request mapping) in the reference manual (RM0368).
+     */
+    __DMA1_CLK_ENABLE();
+    __TIM2_CLK_ENABLE();
+    __GPIOA_CLK_ENABLE();
+
+    hdma_tim.Instance = DMA1_Stream6;
+
+    hdma_tim.Init.Channel             = DMA_CHANNEL_3;
+    hdma_tim.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+    hdma_tim.Init.PeriphInc           = DMA_PINC_DISABLE;
+    hdma_tim.Init.MemInc              = DMA_MINC_ENABLE;
+    hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+    hdma_tim.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+    hdma_tim.Init.Mode                = DMA_NORMAL;
+    hdma_tim.Init.Priority            = DMA_PRIORITY_HIGH;
+    hdma_tim.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
+    hdma_tim.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+    hdma_tim.Init.MemBurst            = DMA_MBURST_SINGLE;
+    hdma_tim.Init.PeriphBurst         = DMA_PBURST_SINGLE;
+
+    /* Link hdma_tim to hdma[2] (channel3) */
+    __HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC2], hdma_tim);
+
+    /* Initialize TIMx DMA handle */
+    if (HAL_DMA_Init(&hdma_tim) != HAL_OK) {
+      Error_Handler();
+    }
+  }
+}
+
+void HAL_UART_MspInit(UART_HandleTypeDef* huart)
+{
+  GPIO_InitTypeDef GPIO_InitStruct;
+
+  if (huart->Instance == USART1) {
+    /* Peripheral clock enable */
+    __USART1_CLK_ENABLE();
+
+    /**USART1 GPIO Configuration
+    PA9     ------> USART1_TX
+    PA10    ------> USART1_RX
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
+    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    /* NVIC for interrupt mode */
+    HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
+    HAL_NVIC_EnableIRQ(USART1_IRQn);
+  } else if (huart->Instance == USART2) {
+    /* Peripheral clock enable */
+    __USART2_CLK_ENABLE();
+    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
+    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    /* NVIC for interrupt mode */
+    HAL_NVIC_SetPriority(USART2_IRQn, 0, 1);
+    HAL_NVIC_EnableIRQ(USART2_IRQn);
+  }
+}
+
+void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
+{
+  if (huart->Instance == USART1) {
+    /* Peripheral clock disable */
+    __USART1_CLK_DISABLE();
+
+    /**USART1 GPIO Configuration
+    PA9     ------> USART1_TX
+    PA10    ------> USART1_RX
+    */
+    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
+  } else if (huart->Instance == USART2) {
+    __USART2_CLK_DISABLE();
+    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2 | GPIO_PIN_3);
+  }
+}
+
+/**
+  * @brief  This function is executed in case of error occurrence.
+  * @param  None
+  * @retval None
+  */
+static void Error_Handler(void)
+{
+  /* Turn on RED LED and then loop indefinitely */
+  HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+
+  while (1) { ; }
+}
diff --git a/src/cc20rng/stm32f4xx_it.c b/src/cc20rng/stm32f4xx_it.c
new file mode 100644
index 0000000..d60a229
--- /dev/null
+++ b/src/cc20rng/stm32f4xx_it.c
@@ -0,0 +1,208 @@
+/**
+  ******************************************************************************
+  * @file    GPIO/GPIO_IOToggle/Src/stm32f4xx_it.c
+  * @author  MCD Application Team
+  * @version V1.0.1
+  * @date    26-February-2014
+  * @brief   Main Interrupt Service Routines.
+  *          This file provides template for all exceptions handler and
+  *          peripherals interrupt service routine.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * 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.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_it.h"
+#include "stm_init.h"
+
+/** @addtogroup STM32F4xx_HAL_Examples
+  * @{
+  */
+
+/** @addtogroup GPIO_IOToggle
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/******************************************************************************/
+/*            Cortex-M4 Processor Exceptions Handlers                         */
+/******************************************************************************/
+
+/**
+  * @brief   This function handles NMI exception.
+  * @param  None
+  * @retval None
+  */
+void NMI_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles Hard Fault exception.
+  * @param  None
+  * @retval None
+  */
+void HardFault_Handler(void)
+{
+  /* Go to infinite loop when Hard Fault exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles Memory Manage exception.
+  * @param  None
+  * @retval None
+  */
+void MemManage_Handler(void)
+{
+  /* Go to infinite loop when Memory Manage exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles Bus Fault exception.
+  * @param  None
+  * @retval None
+  */
+void BusFault_Handler(void)
+{
+  /* Go to infinite loop when Bus Fault exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles Usage Fault exception.
+  * @param  None
+  * @retval None
+  */
+void UsageFault_Handler(void)
+{
+  /* Go to infinite loop when Usage Fault exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles SVCall exception.
+  * @param  None
+  * @retval None
+  */
+void SVC_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles Debug Monitor exception.
+  * @param  None
+  * @retval None
+  */
+void DebugMon_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles PendSVC exception.
+  * @param  None
+  * @retval None
+  */
+void PendSV_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles SysTick Handler.
+  * @param  None
+  * @retval None
+  */
+void SysTick_Handler(void)
+{
+  HAL_IncTick();
+}
+
+/******************************************************************************/
+/*                 STM32F4xx Peripherals Interrupt Handlers                   */
+/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
+/*  available peripheral interrupt handler's name please refer to the startup */
+/*  file (startup_stm32f4xx.s).                                               */
+/******************************************************************************/
+
+/**
+ * @brief  This function handles UART interrupt request.
+ * @param  None
+ * @retval None
+ * @Note   HAL_UART_IRQHandler will call HAL_UART_TxCpltCallback in main.c.
+ */
+void USART1_IRQHandler(void)
+{
+  HAL_UART_IRQHandler(&huart1);
+}
+
+/**
+ * @brief  This function handles UART interrupt request.
+ * @param  None
+ * @retval None
+ * @Note   HAL_UART_IRQHandler will call HAL_UART_TxCpltCallback in main.c.
+ */
+void USART2_IRQHandler(void)
+{
+  HAL_UART_IRQHandler(&huart2);
+}
+
+/**
+ * @brief  This function handles DMA1 Stream 6 interrupt request.
+ * @param  None
+ * @retval None
+ */
+void DMA1_Stream6_IRQHandler(void)
+{
+  HAL_DMA_IRQHandler(&hdma_tim);
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/cc20rng/stm32f4xx_it.h b/src/cc20rng/stm32f4xx_it.h
new file mode 100644
index 0000000..04c5a36
--- /dev/null
+++ b/src/cc20rng/stm32f4xx_it.h
@@ -0,0 +1,70 @@
+/**
+  ******************************************************************************
+  * @file    GPIO/GPIO_IOToggle/Inc/stm32f4xx_it.h
+  * @author  MCD Application Team
+  * @version V1.0.1
+  * @date    26-February-2014
+  * @brief   This file contains the headers of the interrupt handlers.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * 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.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_IT_H
+#define __STM32F4xx_IT_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void SVC_Handler(void);
+void DebugMon_Handler(void);
+void PendSV_Handler(void);
+void SysTick_Handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_IT_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/cc20rng/stm_init.c b/src/cc20rng/stm_init.c
new file mode 100644
index 0000000..548f57b
--- /dev/null
+++ b/src/cc20rng/stm_init.c
@@ -0,0 +1,290 @@
+/**
+  ******************************************************************************
+  * @file    GPIO/GPIO_IOToggle/Src/main.c
+  * @author  MCD Application Team
+  * @version V1.0.1
+  * @date    26-February-2014
+  * @brief   This example describes how to configure and use GPIOs through
+  *          the STM32F4xx HAL API.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * 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.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm_init.h"
+
+/** @addtogroup STM32F4xx_HAL_Examples
+  * @{
+  */
+
+/** @addtogroup GPIO_IOToggle
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+#define UART1_BAUD_RATE 921600  /* FTDI/USB */
+#define UART2_BAUD_RATE 115200  /* R-Pi GPIO */
+
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+
+static GPIO_InitTypeDef  GPIO_InitStruct;
+TIM_HandleTypeDef htim2;
+UART_HandleTypeDef huart1;
+UART_HandleTypeDef huart2;
+DMA_HandleTypeDef hdma_tim;
+
+/* Private function prototypes -----------------------------------------------*/
+static void SystemClock_Config(void);
+static void MX_GPIO_Init(void);
+static void MX_TIM2_Init(uint32_t *counters_buf, uint16_t counters);
+static void MX_USART1_UART_Init(void);
+static void MX_USART2_UART_Init(void);
+/* Private functions ---------------------------------------------------------*/
+
+extern void Error_Handler(void);
+
+
+/**
+  * @brief  Main program
+  * @param  None
+  * @retval None
+  */
+void stm_init(uint32_t *buf0, uint16_t counters)
+{
+ /* Generic STM32 initialization.
+
+    To proceed, 3 steps are required: */
+
+  /* STM32F4xx HAL library initialization:
+       - Configure the Flash prefetch, instruction and Data caches
+       - Configure the Systick to generate an interrupt each 1 msec
+       - Set NVIC Group Priority to 4
+       - Global MSP (MCU Support Package) initialization
+     */
+  HAL_Init();
+
+  /* Configure the system clock */
+  SystemClock_Config();
+
+  /* System interrupt init*/
+  /* Sets the priority grouping field */
+  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
+  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
+
+  /* Initialize all configured peripherals */
+  MX_GPIO_Init();
+  MX_TIM2_Init(buf0, counters);
+  MX_USART1_UART_Init();
+  MX_USART2_UART_Init();
+}
+
+
+/**
+  * @brief  System Clock Configuration
+  *         The system Clock is configured as follow :
+  *            System Clock source            = PLL (HSE)
+  *            SYSCLK(Hz)                     = 42000000
+  *            HCLK(Hz)                       = 42000000
+  *            AHB Prescaler                  = 1
+  *            APB1 Prescaler                 = 1
+  *            APB2 Prescaler                 = 1
+  *            HSI Frequency(Hz)              = 16000000
+  *            PLL_M                          = 8
+  *            PLL_N                          = 336
+  *            PLL_P                          = 8
+  *            PLL_Q                          = 7 (unused)
+  *            VDD(V)                         = 3.3
+  *            Main regulator output voltage  = Scale2 mode
+  *            Flash Latency(WS)              = 1
+  * @param  None
+  * @retval None
+  */
+static void SystemClock_Config(void)
+{
+  RCC_ClkInitTypeDef RCC_ClkInitStruct;
+  RCC_OscInitTypeDef RCC_OscInitStruct;
+
+  /* Enable Power Control clock */
+  __PWR_CLK_ENABLE();
+
+  /* The voltage scaling allows optimizing the power consumption when the device is
+     clocked below the maximum system frequency, to update the voltage scaling value
+     regarding system frequency refer to product datasheet.  */
+  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
+
+  /* Enable HSE Oscillator and activate PLL with HSE as source.
+   *
+   * With 8 MHz HSE oscillator, M=/8, N=*336, P=/8 gives 42 MHz SYSCLK.
+   * Divider Q is unused in this configuration.
+   */
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+  RCC_OscInitStruct.PLL.PLLM = 8;
+  RCC_OscInitStruct.PLL.PLLN = 336;
+  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8;
+  RCC_OscInitStruct.PLL.PLLQ = 7;
+
+  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
+    Error_Handler();
+  }
+
+  /* Select PLL as system clock source */
+  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
+  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;		/* AHB prescaler */
+  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;		/* APB1 prescaler /1 gives 42 MHz APB1 */
+  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;		/* APB2 prescaler /1 gives 42 MHz APB2 */
+  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
+    Error_Handler();
+  }
+
+}
+
+
+/** Configure pins as
+
+     PB12   ------> GREEN LED
+     PB13   ------> YELLOW LED
+     PB14   ------> GREEN lED
+     PB15   ------> BLUE LED
+     PA1    ------> TIM2_CH2 (Avalanche noise)
+*/
+void MX_GPIO_Init(void)
+{
+  /* GPIO Ports Clock Enable */
+  __GPIOA_CLK_ENABLE();
+  __GPIOB_CLK_ENABLE();
+  __GPIOC_CLK_ENABLE();
+
+  /*Configure LED GPIO pins PB12==red, PB13==yellow, PB14==green, PB15==blue */
+  GPIO_InitStruct.Pin = LED_RED | LED_YELLOW | LED_GREEN | LED_BLUE;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+  HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
+
+  /* Configure PA1 (TIM2_Channel2) (Avalanche noise trigger) */
+  GPIO_InitStruct.Pin = GPIO_PIN_1;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_PULLUP;
+  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
+  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+}
+
+/* TIM2 init function.
+ * TIM2 is used in capture mode, triggered off the avalanche noise pin PA1.
+ */
+void MX_TIM2_Init(uint32_t *counters_buf, uint16_t counters)
+{
+  TIM_IC_InitTypeDef sICConfig;
+
+  __DMA1_CLK_ENABLE();
+  __TIM2_CLK_ENABLE();
+  __GPIOA_CLK_ENABLE();
+
+  htim2.Instance = TIM2;
+  htim2.Init.Prescaler = 0;
+  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
+  htim2.Init.Period = 0xffff;
+  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+  htim2.Init.RepetitionCounter = 0;
+
+  /* Configure the Input Capture of channel 2.
+   * Trigger on rising edge. ICFilter = 0 means trigger on every event.
+   */
+  sICConfig.ICPolarity  = TIM_ICPOLARITY_RISING;
+  sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
+  sICConfig.ICPrescaler = TIM_ICPSC_DIV1;
+  sICConfig.ICFilter    = 0;  /* If set - Ignore additional state changes for a short while */
+
+  if (HAL_TIM_IC_Init(&htim2) != HAL_OK) {
+    /* Initialization Error */
+    Error_Handler();
+  }
+
+  if (HAL_TIM_IC_ConfigChannel(&htim2, &sICConfig, TIM_CHANNEL_2) != HAL_OK) {
+    /* Initialization Error */
+    Error_Handler();
+  }
+
+  /* Start the TIM input capture operation */
+  if (HAL_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_2, counters_buf, counters) != HAL_OK) {
+    /* Starting Error */
+    Error_Handler();
+  }
+}
+
+
+/* USART1 init function
+ *
+ * USART1 uses PA9 and PA10.
+ */
+void MX_USART1_UART_Init(void)
+{
+  huart1.Instance          = USART1;
+  huart1.Init.BaudRate     = UART1_BAUD_RATE;
+  huart1.Init.WordLength   = UART_WORDLENGTH_8B;
+  huart1.Init.StopBits     = UART_STOPBITS_1;
+  huart1.Init.Parity       = UART_PARITY_NONE;
+  huart1.Init.Mode         = UART_MODE_TX_RX;
+  huart1.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
+  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
+
+  if (HAL_UART_Init(&huart1) != HAL_OK) {
+    /* Initialization Error */
+    Error_Handler();
+  }
+}
+
+/* USART2 init function */
+void MX_USART2_UART_Init(void)
+{
+  huart2.Instance          = USART2;
+  huart2.Init.BaudRate     = UART2_BAUD_RATE;
+  huart2.Init.WordLength   = UART_WORDLENGTH_8B;
+  huart2.Init.StopBits     = UART_STOPBITS_1;
+  huart2.Init.Parity       = UART_PARITY_NONE;
+  huart2.Init.Mode         = UART_MODE_TX_RX;
+  huart2.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
+  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
+
+  if (HAL_UART_Init(&huart2) != HAL_OK) {
+    /* Initialization Error */
+    Error_Handler();
+  }
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/cc20rng/stm_init.h b/src/cc20rng/stm_init.h
new file mode 100644
index 0000000..d58c254
--- /dev/null
+++ b/src/cc20rng/stm_init.h
@@ -0,0 +1,18 @@
+#ifndef __STM_INIT_H
+#define __STM_INIT_H
+
+#include "stm32f4xx_hal.h"
+
+#define LED_PORT	GPIOB
+#define LED_RED		GPIO_PIN_12
+#define LED_YELLOW	GPIO_PIN_13
+#define LED_GREEN	GPIO_PIN_14
+#define LED_BLUE	GPIO_PIN_15
+
+extern UART_HandleTypeDef huart1;
+extern UART_HandleTypeDef huart2;
+extern DMA_HandleTypeDef hdma_tim;
+
+extern void stm_init(uint32_t *buf0, uint16_t counters);
+
+#endif /* __STM_INIT_H */
diff --git a/src/cc20rng/system_stm32f4xx.c b/src/cc20rng/system_stm32f4xx.c
new file mode 100644
index 0000000..35f79ba
--- /dev/null
+++ b/src/cc20rng/system_stm32f4xx.c
@@ -0,0 +1,270 @@
+/**
+  ******************************************************************************
+  * @file    system_stm32f4xx.c
+  * @author  MCD Application Team
+  * @version V1.0.1
+  * @date    26-February-2014
+  * @brief   CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
+  *
+  *   This file provides two functions and one global variable to be called from
+  *   user application:
+  *      - SystemInit(): This function is called at startup just after reset and
+  *                      before branch to main program. This call is made inside
+  *                      the "startup_stm32f4xx.s" file.
+  *
+  *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
+  *                                  by the user application to setup the SysTick
+  *                                  timer or configure other parameters.
+  *
+  *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
+  *                                 be called whenever the core clock is changed
+  *                                 during program execution.
+  *
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+  *
+  * 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.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+  *
+  ******************************************************************************
+  */
+
+/** @addtogroup CMSIS
+  * @{
+  */
+
+/** @addtogroup stm32f4xx_system
+  * @{
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Includes
+  * @{
+  */
+
+#include "stm32f4xx_hal.h"
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Defines
+  * @{
+  */
+
+/************************* Miscellaneous Configuration ************************/
+
+/*!< Uncomment the following line if you need to relocate your vector Table in
+     Internal SRAM. */
+/* #define VECT_TAB_SRAM */
+#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field.
+                                   This value must be a multiple of 0x200. */
+/******************************************************************************/
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Variables
+  * @{
+  */
+  /* This variable is updated in three ways:
+      1) by calling CMSIS function SystemCoreClockUpdate()
+      2) by calling HAL API function HAL_RCC_GetHCLKFreq()
+      3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+         Note: If you use this function to configure the system clock; then there
+               is no need to call the 2 first functions listed above, since SystemCoreClock
+               variable is updated automatically.
+  */
+  uint32_t SystemCoreClock = 16000000;
+  __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  Setup the microcontroller system
+  *         Initialize the FPU setting, vector table location and External memory
+  *         configuration.
+  * @param  None
+  * @retval None
+  */
+void SystemInit(void)
+{
+  /* FPU settings ------------------------------------------------------------*/
+  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
+  #endif
+  /* Reset the RCC clock configuration to the default reset state ------------*/
+  /* Set HSION bit */
+  RCC->CR |= (uint32_t)0x00000001;
+
+  /* Reset CFGR register */
+  RCC->CFGR = 0x00000000;
+
+  /* Reset HSEON, CSSON and PLLON bits */
+  RCC->CR &= (uint32_t)0xFEF6FFFF;
+
+  /* Reset PLLCFGR register */
+  RCC->PLLCFGR = 0x24003010;
+
+  /* Reset HSEBYP bit */
+  RCC->CR &= (uint32_t)0xFFFBFFFF;
+
+  /* Disable all interrupts */
+  RCC->CIR = 0x00000000;
+
+  /* Configure the Vector Table location add offset address ------------------*/
+#ifdef VECT_TAB_SRAM
+  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
+#else
+  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
+#endif
+}
+
+/**
+   * @brief  Update SystemCoreClock variable according to Clock Register Values.
+  *         The SystemCoreClock variable contains the core clock (HCLK), it can
+  *         be used by the user application to setup the SysTick timer or configure
+  *         other parameters.
+  *
+  * @note   Each time the core clock (HCLK) changes, this function must be called
+  *         to update SystemCoreClock variable value. Otherwise, any configuration
+  *         based on this variable will be incorrect.
+  *
+  * @note   - The system frequency computed by this function is not the real
+  *           frequency in the chip. It is calculated based on the predefined
+  *           constant and the selected clock source:
+  *
+  *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
+  *
+  *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
+  *
+  *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
+  *             or HSI_VALUE(*) multiplied/divided by the PLL factors.
+  *
+  *         (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
+  *             16 MHz) but the real value may vary depending on the variations
+  *             in voltage and temperature.
+  *
+  *         (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
+  *              depends on the application requirements), user has to ensure that HSE_VALUE
+  *              is same as the real frequency of the crystal used. Otherwise, this function
+  *              may have wrong result.
+  *
+  *         - The result of this function could be not correct when using fractional
+  *           value for HSE crystal.
+  *
+  * @param  None
+  * @retval None
+  */
+void SystemCoreClockUpdate(void)
+{
+  uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
+
+  /* Get SYSCLK source -------------------------------------------------------*/
+  tmp = RCC->CFGR & RCC_CFGR_SWS;
+
+  switch (tmp)
+  {
+    case 0x00:  /* HSI used as system clock source */
+      SystemCoreClock = HSI_VALUE;
+      break;
+    case 0x04:  /* HSE used as system clock source */
+      SystemCoreClock = HSE_VALUE;
+      break;
+    case 0x08:  /* PLL used as system clock source */
+
+      /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
+         SYSCLK = PLL_VCO / PLL_P
+         */
+      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
+      pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+
+      if (pllsource != 0)
+      {
+        /* HSE used as PLL clock source */
+        pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+      }
+      else
+      {
+        /* HSI used as PLL clock source */
+        pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+      }
+
+      pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
+      SystemCoreClock = pllvco/pllp;
+      break;
+    default:
+      SystemCoreClock = HSI_VALUE;
+      break;
+  }
+  /* Compute HCLK frequency --------------------------------------------------*/
+  /* Get HCLK prescaler */
+  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
+  /* HCLK frequency */
+  SystemCoreClock >>= tmp;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/cc20rng/test.c b/src/cc20rng/test.c
new file mode 100644
index 0000000..e2bdae0
--- /dev/null
+++ b/src/cc20rng/test.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "cc20_prng.h"
+
+int main()
+{
+    uint32_t i;
+    i = chacha20_prng_self_test();
+    printf("test result: %i (%s)\n", i, (i == 0)?"FAIL":"SUCCESS");
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Commits mailing list