summaryrefslogtreecommitdiff
path: root/src/demo.c
diff options
context:
space:
mode:
authorjaseg <git@jaseg.net>2018-11-08 15:41:46 +0900
committerjaseg <git@jaseg.net>2018-11-08 15:41:46 +0900
commit050d49a56bc54c78c3fc1f4f125b09634d6c5b83 (patch)
tree281cee1a4b07a7cc1da1a0c1406877d9707e4df6 /src/demo.c
parent8ee5f4ce6a70e742156c28565fb13ee96ae35a1f (diff)
downloadsecure-hid-050d49a56bc54c78c3fc1f4f125b09634d6c5b83.tar.gz
secure-hid-050d49a56bc54c78c3fc1f4f125b09634d6c5b83.tar.bz2
secure-hid-050d49a56bc54c78c3fc1f4f125b09634d6c5b83.zip
Noise integration compiles
Diffstat (limited to 'src/demo.c')
-rw-r--r--src/demo.c172
1 files changed, 169 insertions, 3 deletions
diff --git a/src/demo.c b/src/demo.c
index fdd61e7..a4debe5 100644
--- a/src/demo.c
+++ b/src/demo.c
@@ -25,6 +25,8 @@
#include "usbh_lld_stm32f4.h" /// provides low level usb host driver for stm32f4 platform
#include "usbh_driver_hid.h" /// provides generic usb device driver for Human Interface Device (HID)
#include "usbh_driver_hub.h" /// provides usb full speed hub driver (Low speed devices on hub are not supported)
+#include "cobs.h"
+#include "rand_stm32.h"
// STM32f407 compatible
#include <libopencm3/stm32/rcc.h>
@@ -41,6 +43,11 @@
#include <string.h>
#include <stdlib.h>
+#include <noise/protocol.h>
+
+void _fini(void);
+int generate_identity_key(void);
+
static inline void delay_ms_busy_loop(uint32_t ms) {
for (volatile uint32_t i = 0; i < 14903*ms; i++);
}
@@ -59,6 +66,8 @@ static void clock_setup(void) {
rcc_periph_clock_enable(RCC_TIM6);
rcc_periph_clock_enable(RCC_DMA2);
rcc_periph_clock_enable(RCC_DMA1);
+
+ rcc_periph_clock_enable(RCC_RNG);
}
@@ -182,6 +191,96 @@ void dma1_stream6_isr(void) {
schedule_dma(usart2_out);
}
+static struct cobs_decode_state host_cobs_state;
+#define CURVE25519_KEY_LEN 32
+#define MAX_HOST_PACKET_SIZE 256
+static volatile uint8_t host_packet_buf[MAX_HOST_PACKET_SIZE];
+static volatile uint8_t host_packet_length = 0;
+
+void usart2_isr(void) {
+ if (USART2_SR & USART_SR_ORE) { /* Overrun handling */
+ LOG_PRINTF("USART2 data register overrun\n");
+ /* Clear interrupt flag */
+ (void)USART2_DR; /* FIXME make sure this read is not optimized out */
+ return;
+ }
+
+ uint8_t data = USART2_DR; /* This automatically acknowledges the IRQ */
+
+ if (host_packet_length) {
+ LOG_PRINTF("USART2 COBS buffer overrun\n");
+ return;
+ }
+
+ ssize_t rv = cobs_decode_incremental(&host_cobs_state, (char *)host_packet_buf, sizeof(host_packet_buf), data);
+ if (rv == -2) {
+ LOG_PRINTF("Host interface COBS packet too large\n");
+ } else if (rv < 0) {
+ LOG_PRINTF("Host interface COBS framing error\n");
+ } else if (rv > 0) {
+ host_packet_length = rv;
+ } /* else just return and wait for next byte */
+}
+
+static uint8_t local_key[CURVE25519_KEY_LEN];
+NoiseCipherState *tx_cipher, *rx_cipher;
+
+#define HANDLE_NOISE_ERROR(x, msg) do { \
+ err = x; \
+ if (err != NOISE_ERROR_NONE) { \
+ char errbuf[256]; \
+ noise_strerror(err, errbuf, sizeof(errbuf)); \
+ LOG_PRINTF("Error " msg ": %s\n", errbuf); \
+ goto errout; \
+ } \
+ } while(0);
+
+static NoiseHandshakeState *start_protocol_handshake(void) {
+ /* TODO Noise-C is nice for prototyping, but we should really get rid of it for mostly two reasons:
+ * * We don't need cipher/protocol agility, and by baking the final protocol into the firmware we can save a lot
+ * of flash space by not including all the primitives we don't need as well as noise's dynamic protocol
+ * abstraction layer.
+ * * Noise-c is not very embedded-friendly, in particular it uses malloc and free. We should be able to run
+ * everything with statically allocated buffers instead.
+ */
+ NoiseHandshakeState *handshake;
+ int err;
+
+ HANDLE_NOISE_ERROR(noise_init(), "initializing noise");
+
+ HANDLE_NOISE_ERROR(noise_handshakestate_new_by_name(&handshake, "Noise_XX_25519_ChaChaPoly_BLAKE2s", NOISE_ROLE_RESPONDER), "instantiating handshake pattern");
+
+ NoiseDHState *dh = noise_handshakestate_get_local_keypair_dh(handshake);
+ HANDLE_NOISE_ERROR(noise_dhstate_set_keypair_private(dh, local_key, sizeof(local_key)), "loading local private keys");
+
+ HANDLE_NOISE_ERROR(noise_handshakestate_start(handshake), "starting handshake");
+
+ return handshake;
+
+errout:
+ noise_handshakestate_free(handshake);
+ return 0;
+}
+
+int generate_identity_key(void) {
+ NoiseDHState *dh;
+ int err;
+
+ HANDLE_NOISE_ERROR(noise_dhstate_new_by_name(&dh, "25519"), "creating dhstate for key generation");
+ HANDLE_NOISE_ERROR(noise_dhstate_generate_keypair(dh), "generating key pair");
+
+ uint8_t unused[CURVE25519_KEY_LEN]; /* the noise api is a bit bad here. */
+ memset(local_key, 0, sizeof(local_key));
+
+ HANDLE_NOISE_ERROR(noise_dhstate_get_keypair(dh, local_key, sizeof(local_key), unused, sizeof(unused)), "saving key pair");
+
+ return 0;
+
+errout:
+ if (dh)
+ noise_dhstate_free(dh);
+ return -1;
+}
int main(void)
{
@@ -194,12 +293,17 @@ int main(void)
#ifdef USART_DEBUG
usart_dma_init(debug_out);
#endif
+
usart_dma_init(usart2_out);
+ cobs_decode_incremental_initialize(&host_cobs_state);
+ usart_enable_rx_interrupt(USART2);
+ nvic_enable_irq(NVIC_USART2_IRQ);
LOG_PRINTF("\n==================================\n");
LOG_PRINTF("SecureHID device side initializing\n");
LOG_PRINTF("==================================\n");
+ LOG_PRINTF("Initializing USB...\n");
hid_driver_init(&hid_config);
hub_driver_init();
@@ -212,7 +316,18 @@ int main(void)
*/
usbh_init(lld_drivers, device_drivers);
- LOG_PRINTF("USB init complete\n");
+ LOG_PRINTF("Initializing RNG...\n");
+ rand_init();
+
+ /* FIXME only run this on first boot and persist key in backup sram. Allow reset via jumper-triggered factory reset function. */
+ LOG_PRINTF("Generating identity key...\n");
+ if (generate_identity_key())
+ LOG_PRINTF("Error generating identiy key\n");
+
+ LOG_PRINTF("Starting noise protocol handshake...\n");
+ NoiseHandshakeState *handshake = start_protocol_handshake();
+ if (!handshake)
+ LOG_PRINTF("Error starting protocol handshake.\n");
int i = 0, j = 0;
while (23) {
@@ -220,10 +335,61 @@ int main(void)
delay_ms_busy_loop(1); /* approx 1ms interval between usbh_poll() */
if (i++ == 1000) {
i = 0;
- const char *s = "foobarfoobarfoobarfoobarfoobar";
- send_packet(usart2_out, (uint8_t *)s, strlen(s));
LOG_PRINTF("Loop iteration %d\n", 1000*(j++));
}
+
+ if (handshake) {
+#define MAX_MESSAGE_LEN 256
+ uint8_t message[MAX_MESSAGE_LEN];
+ NoiseBuffer noise_msg;
+ /* Run the protocol handshake */
+ switch (noise_handshakestate_get_action(handshake)) {
+ case NOISE_ACTION_WRITE_MESSAGE:
+ /* Write the next handshake message with a zero-length payload */
+ noise_buffer_set_output(noise_msg, message, sizeof(message));
+ if (noise_handshakestate_write_message(handshake, &noise_msg, NULL) != NOISE_ERROR_NONE) {
+ LOG_PRINTF("Error writing handshake message\n");
+ noise_handshakestate_free(handshake);
+ handshake = NULL;
+ }
+ send_packet(usart2_out, message, noise_msg.size);
+ break;
+
+ case NOISE_ACTION_READ_MESSAGE:
+ if (host_packet_length > 0) {
+ /* Read the next handshake message and discard the payload */
+ noise_buffer_set_input(noise_msg, (uint8_t *)host_packet_buf, host_packet_length);
+ if (noise_handshakestate_read_message(handshake, &noise_msg, NULL) != NOISE_ERROR_NONE) {
+ LOG_PRINTF("Error reading handshake message\n");
+ noise_handshakestate_free(handshake);
+ handshake = NULL;
+ }
+ }
+ break;
+
+ case NOISE_ACTION_SPLIT:
+ if (noise_handshakestate_split(handshake, &tx_cipher, &rx_cipher) != NOISE_ERROR_NONE) {
+ LOG_PRINTF("Error splitting handshake state\n");
+ } else {
+ LOG_PRINTF("Noise protocol handshake completed successfully\n");
+ }
+
+ noise_handshakestate_free(handshake);
+ handshake = NULL;
+ break;
+
+ default:
+ LOG_PRINTF("Noise protocol handshake failed\n");
+ noise_handshakestate_free(handshake);
+ handshake = 0;
+ break;
+ }
+ }
}
return 0;
}
+
+void _fini() {
+ while (1);
+}
+