Added FIPS 140-2 sanity check to usbtrng-v2.0
authorTom Marble <tmarble@info9.net>
Wed, 11 Mar 2015 20:12:11 +0000 (15:12 -0500)
committerTom Marble <tmarble@info9.net>
Wed, 11 Mar 2015 20:12:11 +0000 (15:12 -0500)
src/drivers/ao_trng.c
src/drivers/ao_trng.h
src/usbtrng-v2.0/ao_usbtrng.c

index db7429282620fac4fef34aa00c216cba4b9d8bf3..b8e25e289c01dcc21ded0f02211372174f176fa9 100644 (file)
 #include <ao_crc.h>
 #include <ao_trng.h>
 
+
+static struct ao_task ao_blink_red_task;
+static uint8_t ao_failed = 0;
+
+static void
+ao_blink_red(void)
+{
+       for (;;) {
+               while (!ao_failed)
+                       ao_sleep(&ao_failed);
+               while (ao_failed) {
+                       ao_led_toggle(AO_LED_RED);
+                       ao_delay(AO_MS_TO_TICKS(500));
+               }
+       }
+}
+
+static struct ao_task ao_blink_green_task;
+static uint8_t ao_blinking_green = 0;
+
+static void
+ao_blink_green(void)
+{
+       for (;;) {
+               while (!ao_blinking_green)
+                       ao_sleep(&ao_blinking_green);
+               while (ao_blinking_green) {
+                       ao_led_toggle(AO_LED_GREEN);
+                       ao_delay(AO_MS_TO_TICKS(1000));
+               }
+       }
+}
+
+
+static void
+ao_blink_green_toggle(void)
+{
+       ao_blinking_green = !ao_blinking_green;
+       if (!ao_blinking_green)
+               ao_led_off(AO_LED_GREEN);
+       ao_wakeup(&ao_blinking_green);
+}
+
+#define ADC_WORDS (AO_USB_IN_SIZE / sizeof (uint16_t))
+static uint16_t prev16 = 0;
+static uint16_t        adc_values[ADC_WORDS];
+static uint8_t adc_i = ADC_WORDS;
+
+static uint16_t
+fetch16(uint8_t initialize)
+{
+       uint32_t        *rnd;
+       uint8_t         i;
+
+       if (ao_failed)
+               return 0;
+       if (initialize)
+               adc_i = ADC_WORDS;
+       if (adc_i == ADC_WORDS) {
+               rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE);  /* one 16-bit value per output byte */
+               adc_i = 0;
+               for (i = 0; i < ADC_WORDS; i++) {
+                       adc_values[i] = ao_crc_in_32_out_16(*rnd++);
+               }
+       }
+       if (initialize)
+               prev16 = adc_values[adc_i++];
+       if (adc_values[adc_i] == prev16) {
+               /* FAILED: how do we prevent spewing bad data? */
+               printf("FAILED value %d repeated\n", prev16);
+               ao_failed = 1;
+               ao_wakeup(&ao_failed);
+               return 0;
+       }
+       prev16 = adc_values[adc_i];
+       adc_i++;
+       return prev16;
+}
+
+static void
+ao_simulate_failure(void)
+{
+       if (adc_i == ADC_WORDS)
+               fetch16(0);
+       prev16 = adc_values[adc_i];
+}
+
+/* NOTE: the reset function also functions as the Power On Self Test */
+void
+ao_reset(void)
+{
+       uint32_t        count;
+
+       printf("Power On Self Test\n"); /* DEBUGGING */
+       ao_failed = 0;
+       ao_led_off(AO_LED_RED);
+       ao_wakeup(&ao_failed);
+       fetch16(1);
+       /* get the first 1k bits and ensure there are no duplicates */
+       count = 1024 / sizeof (uint16_t);
+       while (count-- && !ao_failed) {
+               fetch16(0);
+       }
+       if (ao_failed) { /* show failure */
+               printf("FAILED self test\n");
+       } else { /* show success */
+               printf("PASS - operation NOMINAL\n");
+               /* this blocks! */
+               ao_led_on(AO_LED_GREEN);
+               ao_delay(AO_MS_TO_TICKS(1000));
+               ao_led_off(AO_LED_GREEN);
+       }
+}
+
 static void
 ao_trng_fetch(void)
 {
@@ -29,7 +143,6 @@ ao_trng_fetch(void)
        int             usb_buf_id;
        uint16_t        i;
        uint16_t        *buf;
-       uint32_t        *rnd;
 
        if (!buffer[0]) {
                buffer[0] = ao_usb_alloc();
@@ -50,10 +163,9 @@ ao_trng_fetch(void)
 
        ao_led_on(AO_LED_TRNG_READ);
        while (count--) {
-               rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE);  /* one 16-bit value per output byte */
                buf = buffer[usb_buf_id];
                for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++)
-                       *buf++ = ao_crc_in_32_out_16(*rnd++);
+                       *buf++ = fetch16(0);
                ao_adc_ack(AO_USB_IN_SIZE);
                ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
                ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
@@ -64,13 +176,35 @@ ao_trng_fetch(void)
        flush();
 }
 
+static void
+ao_trng_word(void)
+{
+       printf("%d\n", fetch16(0));
+}
+
+static void
+ao_status(void)
+{
+       if (ao_failed)
+               printf("FAILED\n");
+       else
+               printf("NOMINAL\n");
+}
+
 static const struct ao_cmds ao_trng_cmds[] = {
-       { ao_trng_fetch,        "f <kbytes>\0Fetch a block of numbers" },
+       { ao_trng_fetch, "f <kbytes>\0Fetch a block of numbers" },
+       { ao_trng_word, "F\0Fetch 16 bit unsigned int" },
+       { ao_reset, "R\0reset" },
+       { ao_blink_green_toggle, "G\0Toggle green LED blinking" },
+       { ao_status, "s\0show status" },
+       { ao_simulate_failure, "z\0simulate failure" },
        { 0, NULL },
 };
 
 void
 ao_trng_init(void)
 {
+       ao_add_task(&ao_blink_red_task, ao_blink_red, "blink_red");
+       ao_add_task(&ao_blink_green_task, ao_blink_green, "blink_green");
        ao_cmd_register(ao_trng_cmds);
 }
index 78577428f5a6edcb5550b36f6d913ca1cdc99b34..089c70c608a8cff709b634a9d9ebf146856780f6 100644 (file)
@@ -21,4 +21,7 @@
 void
 ao_trng_init(void);
 
+void
+ao_reset(void);
+
 #endif /* _AO_TRNG_H_ */
index 42713b6ec842fb2023e9e4441527cdbdf6e5ed08..d4a751970adf56d698e15e0aeb322aa034ea001b 100644 (file)
@@ -40,4 +40,6 @@ void main(void)
        ao_led_off(AO_LED_RED);
 
        ao_start_scheduler();
+
+       ao_reset(); /* Power On Self Test */
 }