filter by CRC32
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 3 Oct 2012 00:16:38 +0000 (09:16 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 3 Oct 2012 00:16:38 +0000 (09:16 +0900)
ChangeLog
src/adc.h
src/adc_stm32f103.c
src/neug.h
src/random.c

index 7119a73..fc93043 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2012-10-03  Niibe Yutaka  <gniibe@fsij.org>
+
+       * src/adc_stm32f103.c (adc_lld_serve_rx_interrupt)
+       (adc_start_conversion): Filter by CRC32.
+       * src/random.c (ep_init, ep_fill_wbuf, ep_process): Filter by CRC32.
+       (neug_init): CRC32 initialization.
+
 2012-10-02  Niibe Yutaka  <gniibe@fsij.org>
 
        * src/random.c: Use our own ADC driver.
index b7c3b08..2874520 100644 (file)
--- a/src/adc.h
+++ b/src/adc.h
@@ -1,10 +1,13 @@
 #define ADC_DATA_AVAILABLE ((eventmask_t)1)
 extern Thread *rng_thread;
 
-#define NEUG_SAMPLE_BUFSIZE     512
-extern uint16_t adc_samp[NEUG_SAMPLE_BUFSIZE];
+#define NEUG_SAMPLE_BUFSIZE     1024
+extern uint8_t adc_samp[NEUG_SAMPLE_BUFSIZE];
 
 void adc_init (void);
 void adc_start (void);
-void adc_start_conversion (int offset, int size);
 void adc_stop (void);
+
+#define ADC_SAMPLE_MODE 0
+#define ADC_CRC32_MODE  1
+void adc_start_conversion (int mode, int offset, int size);
index ae32652..35d8aef 100644 (file)
@@ -27,6 +27,8 @@
 #include "neug.h"
 #include "adc.h"
 
+#define NEUG_CRC32_COUNTS 3
+
 #define STM32_ADC_ADC1_DMA_PRIORITY         2
 #define STM32_ADC_ADC1_IRQ_PRIORITY         5
 
 /*
  * ADC samples buffer.
  */
-uint16_t adc_samp[NEUG_SAMPLE_BUFSIZE];
+uint8_t adc_samp[NEUG_SAMPLE_BUFSIZE] __attribute__((aligned (4)));
 
 #define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
-#define NEUG_DMA_MODE (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)     \
-                      | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD \
-                      | STM32_DMA_CR_MINC       | STM32_DMA_CR_TCIE       \
-                      | STM32_DMA_CR_TEIE)
+#define NEUG_DMA_MODE_SAMPLE                                            \
+  (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)                     \
+     | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD               \
+     | STM32_DMA_CR_MINC       | STM32_DMA_CR_TCIE                     \
+     | STM32_DMA_CR_TEIE)
+
+#define NEUG_DMA_MODE_CRC32                                             \
+  (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)                     \
+     | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD               \
+     | STM32_DMA_CR_TCIE       | STM32_DMA_CR_TEIE)
 
 #define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF)
 #define NEUG_ADC_SETTING1_SMPR2 0
@@ -153,15 +161,12 @@ void adc_start (void)
   chSysUnlock ();
 }
 
-void adc_start_conversion (int offset, int size)
-{
-  uint16_t *p = adc_samp + offset;
-
-  dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, p);
-  dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, size);
-  dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE);
-  dmaStreamEnable (NEUG_DMA_CHANNEL);
+static int adc_size;
+static int adc_offset;
+static int adc_mode;
 
+static void adc_start_conversion_internal (void)
+{
 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
   /* Power on */
   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
@@ -178,6 +183,48 @@ void adc_start_conversion (int offset, int size)
 #endif
 }
 
+void adc_start_conversion (int mode, int offset, int size)
+{
+  adc_mode = mode;
+  adc_offset = offset;
+  adc_size = size;
+
+ if (mode == ADC_SAMPLE_MODE)
+    {
+      dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, adc_samp + offset);
+      dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, size);
+      dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_SAMPLE);
+      dmaStreamEnable (NEUG_DMA_CHANNEL);
+    }
+  else
+    {
+      dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
+      dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
+      dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
+      dmaStreamEnable (NEUG_DMA_CHANNEL);
+
+      if ((size & 3))
+       {
+         uint32_t v;
+         int i;
+
+         CRC->DR = SysTick->VAL;
+         v = CRC->DR;
+
+         for (i = 0; i < (size & 3); i++)
+           {
+             adc_samp[adc_offset++] = v;
+             v >>= 8;
+           }
+
+         adc_size &= ~3;
+       }
+    }
+
+ adc_start_conversion_internal ();
+}
+
+
 static void adc_stop_conversion (void)
 {
   dmaStreamDisable (NEUG_DMA_CHANNEL);
@@ -209,7 +256,8 @@ static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags)
 
   if ((flags & STM32_DMA_ISR_TEIF) != 0)  /* DMA errors  */
     {
-      /* access an unmapped address space or violates alignment rules.  */
+      /* Should never happened.  If any, it's coding error. */
+      /* Access an unmapped address space or alignment violation.  */
       adc_stop_conversion ();
     }
   else
@@ -217,10 +265,33 @@ static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags)
       if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
        {
          adc_stop_conversion ();
-         chSysLockFromIsr();
-         if (rng_thread)
-           chEvtSignalFlagsI (rng_thread, ADC_DATA_AVAILABLE);
-         chSysUnlockFromIsr();
+
+         if (adc_mode != ADC_SAMPLE_MODE)
+           {
+             uint32_t *p =  (uint32_t *)(&adc_samp[adc_offset]);
+
+             *p = CRC->DR;
+             adc_offset += 4;
+             adc_size -= 4;
+
+             if (adc_size > 0)
+               {
+                 dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
+                 dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
+                 dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
+                 dmaStreamEnable (NEUG_DMA_CHANNEL);
+
+                 adc_start_conversion_internal ();
+               }
+           }
+
+         if (adc_mode == ADC_SAMPLE_MODE || adc_size <= 0)
+           {
+             chSysLockFromIsr();
+             if (rng_thread)
+               chEvtSignalFlagsI (rng_thread, ADC_DATA_AVAILABLE);
+             chSysUnlockFromIsr();
+           }
        }
     }
 }
index c288c8f..7c12aa1 100644 (file)
@@ -4,7 +4,7 @@
 #define NEUG_PRE_LOOP 32
 
 #define NEUG_MODE_CONDITIONED 0
-#define NEUG_MODE_RAW_LSB     1
+#define NEUG_MODE_RAW         1
 #define NEUG_MODE_RAW_DATA    2
 
 void neug_init (uint32_t *buf, uint8_t size);
index 39eb1ad..7ad2a1a 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "ch.h"
 #include "hal.h"
+#include "sys.h"
 #include "neug.h"
 #include "adc.h"
 
@@ -39,11 +40,6 @@ static sha256_context sha256_ctx_data;
 static uint32_t sha256_output[SHA256_DIGEST_SIZE/sizeof (uint32_t)];
 
 /*
- * We did an experiment of measuring entropy of ADC output with MUST.
- * The entropy of a byte by raw sampling of LSBs has more than 6.0 bit/byte.
- *
- * More tests will be required, but for now we assume min-entropy >= 5.0.
- * 
  * To be a full entropy source, the requirement is to have N samples for
  * output of 256-bit, where:
  *
@@ -69,16 +65,16 @@ static uint32_t sha256_output[SHA256_DIGEST_SIZE/sizeof (uint32_t)];
  */
 #define NUM_NOISE_INPUTS 139
 
-#define EP_ROUND_0 0 /* initial-five-byte and 59*8-sample-input */
-#define EP_ROUND_1 1 /* 64*8-sample-input */
-#define EP_ROUND_2 2 /* 16*8-sample-input */
-#define EP_ROUND_RAW_LSB  3 /* 64*8-sample-input */
-#define EP_ROUND_RAW_DATA 4 /* 16-sample-input */
+#define EP_ROUND_0 0 /* initial-five-byte and 59-byte-input */
+#define EP_ROUND_1 1 /* 64-byte-input */
+#define EP_ROUND_2 2 /* 16-byte-input */
+#define EP_ROUND_RAW      3 /* 64-byte-input */
+#define EP_ROUND_RAW_DATA 4 /* 2-sample-input */
 
 #define EP_ROUND_0_INPUTS 59
 #define EP_ROUND_1_INPUTS 64
 #define EP_ROUND_2_INPUTS 16
-#define EP_ROUND_RAW_LSB_INPUTS 64
+#define EP_ROUND_RAW_INPUTS 64
 #define EP_ROUND_RAW_DATA_INPUTS 2
 
 static uint8_t ep_round;
@@ -91,43 +87,35 @@ static uint8_t ep_round;
  */
 static void ep_fill_initial_string (void)
 {
-  memset (adc_samp, 0, 5 * 8 * sizeof (uint16_t));
+  memset (adc_samp, 0, 5);
   adc_samp[0] = 1;
-  adc_samp[3*8] = 1;
+  adc_samp[3] = 1;
 }
 
 static void ep_init (int mode)
 {
   chEvtClearFlags (ADC_DATA_AVAILABLE);
-  if (mode == NEUG_MODE_RAW_LSB)
+  if (mode == NEUG_MODE_RAW)
     {
-      ep_round = EP_ROUND_RAW_LSB;
-      adc_start_conversion (0, EP_ROUND_RAW_LSB_INPUTS*8/2);
+      ep_round = EP_ROUND_RAW;
+      adc_start_conversion (ADC_CRC32_MODE, 0, EP_ROUND_RAW_INPUTS);
     }
   else if (mode == NEUG_MODE_RAW_DATA)
     {
       ep_round = EP_ROUND_RAW_DATA;
-      adc_start_conversion (0, EP_ROUND_RAW_DATA_INPUTS*8/2);
+      adc_start_conversion (ADC_SAMPLE_MODE, 0, EP_ROUND_RAW_DATA_INPUTS);
     }
   else
     {
       ep_round = EP_ROUND_0;
       ep_fill_initial_string ();
-      /*
-       * We get two samples for a single transaction of DMA.
-       * We take LSBs of each samples.
-       * Thus, we need tansactions of: required_number_of_input_in_byte*8/2 
-       */
-      adc_start_conversion (5*8, EP_ROUND_0_INPUTS*8/2);
+      adc_start_conversion (ADC_CRC32_MODE, 5, EP_ROUND_0_INPUTS);
     }
 }
 
 static uint8_t ep_get_byte_from_samples (int i)
 {
-  return (  ((adc_samp[i*8+0] & 1) << 0) | ((adc_samp[i*8+1] & 1) << 1)
-         | ((adc_samp[i*8+2] & 1) << 2) | ((adc_samp[i*8+3] & 1) << 3)
-         | ((adc_samp[i*8+4] & 1) << 4) | ((adc_samp[i*8+5] & 1) << 5)
-         | ((adc_samp[i*8+6] & 1) << 6) | ((adc_samp[i*8+7] & 1) << 7));
+  return adc_samp[i];
 }
 
 static void noise_source_continuous_test (uint8_t noise);
@@ -135,7 +123,10 @@ static void noise_source_continuous_test (uint8_t noise);
 static void ep_fill_wbuf (int i, int flip, int mode)
 {
   if (mode == NEUG_MODE_RAW_DATA)
-    sha256_ctx_data.wbuf[i] = (adc_samp[i*2+1] << 16) | adc_samp[i*2];
+    sha256_ctx_data.wbuf[i] = (adc_samp[i*4]
+                              | (adc_samp[i*4+1] << 8)
+                              | (adc_samp[i*4+2] << 16)
+                              | (adc_samp[i*4+3] << 24));
   else
     {
       uint8_t b0, b1, b2, b3;
@@ -171,9 +162,9 @@ static int ep_process (int mode)
       n = EP_ROUND_2_INPUTS / 4;
       flip = 0;
     }
-  else if (ep_round == EP_ROUND_RAW_LSB)
+  else if (ep_round == EP_ROUND_RAW)
     {
-      n = EP_ROUND_RAW_LSB_INPUTS / 4;
+      n = EP_ROUND_RAW_INPUTS / 4;
       flip = 0;
     }
   else /* ep_round == EP_ROUND_RAW_DATA */
@@ -194,7 +185,7 @@ static int ep_process (int mode)
     {
       if (ep_round == EP_ROUND_0)
        {
-         adc_start_conversion (0, EP_ROUND_1_INPUTS*8/2);
+         adc_start_conversion (ADC_CRC32_MODE, 0, EP_ROUND_1_INPUTS);
          sha256_start (&sha256_ctx_data);
          sha256_process (&sha256_ctx_data);
          ep_round++;
@@ -202,7 +193,7 @@ static int ep_process (int mode)
        }
       else if (ep_round == EP_ROUND_1)
        {
-         adc_start_conversion (0, EP_ROUND_2_INPUTS*8/2);
+         adc_start_conversion (ADC_CRC32_MODE, 0, EP_ROUND_2_INPUTS);
          sha256_process (&sha256_ctx_data);
          ep_round++;
          return 0;
@@ -255,10 +246,16 @@ static void noise_source_error (uint32_t err)
 #endif
 }
 
+/*
+ * For health tests, we assumes that the device noise source has
+ * min-entropy >= 4.2, since observing raw data stream (before CRC-32)
+ * has more than 4.2 bit/byte entropy.
+ *
+ */
 
-/* Cuttoff = 10, when min-entropy = 3.7, W= 2^-30 */
-/* ceiling of (1+30/3.7) */
-#define REPITITION_COUNT_TEST_CUTOFF 10
+/* Cuttoff = 6, when min-entropy = 4.2, W= 2^-30 */
+/* ceiling of (1+30/4.2) */
+#define REPITITION_COUNT_TEST_CUTOFF 8
 
 static uint8_t rct_a;
 static uint8_t rct_b;
@@ -278,9 +275,9 @@ static void repetition_count_test (uint8_t sample)
     }
 }
 
-/* Cuttoff = 22, when min-entropy = 3.7, W= 2^-30 */
-/* With R, qbinom(1-2^-30,64,2^-3.7) */
-#define ADAPTIVE_PROPORTION_64_TEST_CUTOFF 22
+/* Cuttoff = 18, when min-entropy = 4.2, W= 2^-30 */
+/* With R, qbinom(1-2^-30,64,2^-4.2) */
+#define ADAPTIVE_PROPORTION_64_TEST_CUTOFF 18
 
 static uint8_t ap64t_a;
 static uint8_t ap64t_b;
@@ -306,9 +303,9 @@ static void adaptive_proportion_64_test (uint8_t sample)
     }
 }
 
-/* Cuttoff = 422, when min-entropy = 3.7, W= 2^-30 */
-/* With R, qbinom(1-2^-30,4096,2^-3.7) */
-#define ADAPTIVE_PROPORTION_4096_TEST_CUTOFF 422
+/* Cuttoff = 315, when min-entropy = 4.2, W= 2^-30 */
+/* With R, qbinom(1-2^-30,4096,2^-4.2) */
+#define ADAPTIVE_PROPORTION_4096_TEST_CUTOFF 315
 
 static uint8_t ap4096t_a;
 static uint16_t ap4096t_b;
@@ -477,7 +474,19 @@ static WORKING_AREA(wa_rng, 256);
 void
 neug_init (uint32_t *buf, uint8_t size)
 {
+  const uint32_t *u = (const uint32_t *)unique_device_id ();
   struct rng_rb *rb = &the_ring_buffer;
+  int i;
+
+  RCC->AHBENR |= RCC_AHBENR_CRCEN;
+  CRC->CR = CRC_CR_RESET;
+
+  /*
+   * This initialization ensures that it generates different sequence
+   * even if all physical conditions are same.
+   */
+  for (i = 0; i < 3; i++)
+    CRC->DR = *u++;
 
   neug_mode = NEUG_MODE_CONDITIONED;
   rb_init (rb, buf, size);