Update Chopstx and modify configure
[gnuk/neug.git] / src / neug.c
1 /*
2  * neug.c - true random number generation
3  *
4  * Copyright (C) 2011, 2012, 2013, 2016
5  *               Free Software Initiative of Japan
6  * Author: NIIBE Yutaka <gniibe@fsij.org>
7  *
8  * This file is a part of NeuG, a True Random Number Generator
9  * implementation based on quantization error of ADC (for STM32F103).
10  *
11  * NeuG is free software: you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * NeuG is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19  * License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25
26 #include <stdint.h>
27 #include <string.h>
28 #include <chopstx.h>
29
30 #include "sys.h"
31 #include "neug.h"
32 #include "mcu/stm32f103.h"
33 #include "adc.h"
34 #include "sha256.h"
35
36 static chopstx_mutex_t mode_mtx;
37 static chopstx_cond_t  mode_cond;
38
39 static sha256_context sha256_ctx_data;
40 static uint32_t sha256_output[SHA256_DIGEST_SIZE/sizeof (uint32_t)];
41
42 /*
43  * To be a full entropy source, the requirement is to have N samples
44  * for output of 256-bit, where:
45  *
46  *      N = (256 * 2) / <min-entropy of a sample>
47  *
48  * For example, N should be more than 103 for min-entropy = 5.0.
49  *
50  * On the other hand, in the section 6.2 "Full Entropy Source
51  * Requirements", it says:
52  *
53  *     At least twice the block size of the underlying cryptographic
54  *     primitive shall be provided as input to the conditioning
55  *     function to produce full entropy output.
56  *
57  * For us, cryptographic primitive is SHA-256 and its blocksize is
58  * 512-bit (64-byte), thus, N >= 128.
59  *
60  * We chose N=140.  Note that we have "additional bits" of 16-byte for
61  * last block (feedback from previous output of SHA-256) to feed
62  * hash_df function of SHA-256, together with sample data of 140-byte.
63  *
64  * N=140 corresponds to min-entropy >= 3.68.
65  *
66  */
67 #define NUM_NOISE_INPUTS 140
68
69 #define EP_ROUND_0 0 /* initial-five-byte and 3-byte, then 56-byte-input */
70 #define EP_ROUND_1 1 /* 64-byte-input */
71 #define EP_ROUND_2 2 /* 17-byte-input */
72 #define EP_ROUND_RAW      3 /* 32-byte-input */
73 #define EP_ROUND_RAW_DATA 4 /* 32-byte-input */
74
75 #define EP_ROUND_0_INPUTS 56
76 #define EP_ROUND_1_INPUTS 64
77 #define EP_ROUND_2_INPUTS 17
78 #define EP_ROUND_RAW_INPUTS 32
79 #define EP_ROUND_RAW_DATA_INPUTS 32
80
81 static uint8_t ep_round;
82
83 static void noise_source_continuous_test (uint8_t noise);
84 static void noise_source_continuous_test_word (uint8_t b0, uint8_t b1,
85                                                uint8_t b2, uint8_t b3);
86
87 /*
88  * Hash_df initial string:
89  *
90  *  Initial five bytes are:
91  *    1,          : counter = 1
92  *    0, 0, 1, 0  : no_of_bits_returned (in big endian)
93  *
94  *  Then, three-byte from noise source follows.
95  *
96  *  One-byte was used in the previous turn, and we have three bytes in
97  *  CRC->DR.
98  */
99 static void ep_fill_initial_string (void)
100 {
101   uint32_t v = CRC->DR;
102   uint8_t b1, b2, b3;
103
104   b3 = v >> 24;
105   b2 = v >> 16;
106   b1 = v >> 8;
107
108   noise_source_continuous_test (b1);
109   noise_source_continuous_test (b2);
110   noise_source_continuous_test (b3);
111
112   adc_buf[0] = 0x01000001;
113   adc_buf[1] = (v & 0xffffff00);
114 }
115
116 static void ep_init (int mode)
117 {
118   if (mode == NEUG_MODE_RAW)
119     {
120       ep_round = EP_ROUND_RAW;
121       adc_start_conversion (0, EP_ROUND_RAW_INPUTS);
122     }
123   else if (mode == NEUG_MODE_RAW_DATA)
124     {
125       ep_round = EP_ROUND_RAW_DATA;
126       adc_start_conversion (0, EP_ROUND_RAW_DATA_INPUTS / 4);
127     }
128   else
129     {
130       ep_round = EP_ROUND_0;
131       ep_fill_initial_string ();
132       adc_start_conversion (2, EP_ROUND_0_INPUTS);
133     }
134 }
135
136
137 static void ep_fill_wbuf_v (int i, int test, uint32_t v)
138 {
139   if (test)
140     {
141       uint8_t b0, b1, b2, b3;
142
143       b3 = v >> 24;
144       b2 = v >> 16;
145       b1 = v >> 8;
146       b0 = v;
147
148       noise_source_continuous_test_word (b0, b1, b2, b3);
149     }
150
151   sha256_ctx_data.wbuf[i] = v;
152 }
153
154 /* Here, we assume a little endian architecture.  */
155 static int ep_process (int mode)
156 {
157   int i, n;
158   uint32_t v;
159
160   if (ep_round == EP_ROUND_0)
161     {
162       sha256_start (&sha256_ctx_data);
163       sha256_ctx_data.wbuf[0] = adc_buf[0];
164       sha256_ctx_data.wbuf[1] = adc_buf[1];
165       for (i = 0; i < EP_ROUND_0_INPUTS / 4; i++)
166         {
167           CRC->DR = adc_buf[i*4 + 2];
168           CRC->DR = adc_buf[i*4 + 3];
169           CRC->DR = adc_buf[i*4 + 4];
170           CRC->DR = adc_buf[i*4 + 5];
171           v = CRC->DR;
172           ep_fill_wbuf_v (i+2, 1, v);
173         }
174
175       adc_start_conversion (0, EP_ROUND_1_INPUTS);
176       sha256_process (&sha256_ctx_data);
177       ep_round++;
178       return 0;
179     }
180   else if (ep_round == EP_ROUND_1)
181     {
182       for (i = 0; i < EP_ROUND_1_INPUTS / 4; i++)
183         {
184           CRC->DR = adc_buf[i*4];
185           CRC->DR = adc_buf[i*4 + 1];
186           CRC->DR = adc_buf[i*4 + 2];
187           CRC->DR = adc_buf[i*4 + 3];
188           v = CRC->DR;
189           ep_fill_wbuf_v (i, 1, v);
190         }
191
192       adc_start_conversion (0, EP_ROUND_2_INPUTS + 3);
193       sha256_process (&sha256_ctx_data);
194       ep_round++;
195       return 0;
196     }
197   else if (ep_round == EP_ROUND_2)
198     {
199       for (i = 0; i < EP_ROUND_2_INPUTS / 4; i++)
200         {
201           CRC->DR = adc_buf[i*4];
202           CRC->DR = adc_buf[i*4 + 1];
203           CRC->DR = adc_buf[i*4 + 2];
204           CRC->DR = adc_buf[i*4 + 3];
205           v = CRC->DR;
206           ep_fill_wbuf_v (i, 1, v);
207         }
208
209       CRC->DR = adc_buf[i*4];
210       CRC->DR = adc_buf[i*4 + 1];
211       CRC->DR = adc_buf[i*4 + 2];
212       CRC->DR = adc_buf[i*4 + 3];
213       v = CRC->DR & 0xff;   /* First byte of CRC->DR is used here.  */
214       noise_source_continuous_test (v);
215       sha256_ctx_data.wbuf[i] = v;
216       ep_init (NEUG_MODE_CONDITIONED); /* The rest three-byte of
217                                           CRC->DR is used here.  */
218       n = SHA256_DIGEST_SIZE / 2;
219       memcpy (((uint8_t *)sha256_ctx_data.wbuf) + EP_ROUND_2_INPUTS,
220               sha256_output, n);
221       sha256_ctx_data.total[0] = 5 + NUM_NOISE_INPUTS + n;
222       sha256_finish (&sha256_ctx_data, (uint8_t *)sha256_output);
223       return SHA256_DIGEST_SIZE / sizeof (uint32_t);
224     }
225   else if (ep_round == EP_ROUND_RAW)
226     {
227       for (i = 0; i < EP_ROUND_RAW_INPUTS / 4; i++)
228         {
229           CRC->DR = adc_buf[i*4];
230           CRC->DR = adc_buf[i*4 + 1];
231           CRC->DR = adc_buf[i*4 + 2];
232           CRC->DR = adc_buf[i*4 + 3];
233           v = CRC->DR;
234           ep_fill_wbuf_v (i, 1, v);
235         }
236
237       ep_init (mode);
238       return EP_ROUND_RAW_INPUTS / 4;
239     }
240   else if (ep_round == EP_ROUND_RAW_DATA)
241     {
242       for (i = 0; i < EP_ROUND_RAW_DATA_INPUTS / 4; i++)
243         {
244           v = adc_buf[i];
245           ep_fill_wbuf_v (i, 0, v);
246         }
247
248       ep_init (mode);
249       return EP_ROUND_RAW_DATA_INPUTS / 4;
250     }
251
252   return 0;
253 }
254
255
256 static const uint32_t *ep_output (int mode)
257 {
258   if (mode)
259     return sha256_ctx_data.wbuf;
260   else
261     return sha256_output;
262 }
263 \f
264 #define REPETITION_COUNT           1
265 #define ADAPTIVE_PROPORTION_64     2
266 #define ADAPTIVE_PROPORTION_4096   4
267
268 uint8_t neug_err_state;
269 uint16_t neug_err_cnt;
270 uint16_t neug_err_cnt_rc;
271 uint16_t neug_err_cnt_p64;
272 uint16_t neug_err_cnt_p4k;
273
274 uint16_t neug_rc_max;
275 uint16_t neug_p64_max;
276 uint16_t neug_p4k_max;
277
278 static void noise_source_cnt_max_reset (void)
279 {
280   neug_err_cnt = neug_err_cnt_rc = neug_err_cnt_p64 = neug_err_cnt_p4k = 0;
281   neug_rc_max = neug_p64_max = neug_p4k_max = 0;
282 }
283
284 static void noise_source_error_reset (void)
285 {
286   neug_err_state = 0;
287 }
288
289 static void noise_source_error (uint32_t err)
290 {
291   neug_err_state |= err;
292   neug_err_cnt++;
293
294   if ((err & REPETITION_COUNT))
295     neug_err_cnt_rc++;
296   if ((err & ADAPTIVE_PROPORTION_64))
297     neug_err_cnt_p64++;
298   if ((err & ADAPTIVE_PROPORTION_4096))
299     neug_err_cnt_p4k++;
300 }
301
302 /*
303  * For health tests, we assume that the device noise source has
304  * min-entropy >= 4.2.  Observing raw data stream (before CRC-32) has
305  * more than 4.2 bit/byte entropy.  When the data stream after CRC-32
306  * filter will be less than 4.2 bit/byte entropy, that must be
307  * something wrong.  Note that even we observe < 4.2, we still have
308  * some margin, since we use NUM_NOISE_INPUTS=140.
309  *
310  */
311
312 /* Cuttoff = 9, when min-entropy = 4.2, W= 2^-30 */
313 /* ceiling of (1+30/4.2) */
314 #define REPITITION_COUNT_TEST_CUTOFF 9
315
316 static uint8_t rct_a;
317 static uint8_t rct_b;
318
319 static void repetition_count_test (uint8_t sample)
320 {
321   if (rct_a == sample)
322     {
323       rct_b++;
324       if (rct_b >= REPITITION_COUNT_TEST_CUTOFF)
325         noise_source_error (REPETITION_COUNT);
326       if (rct_b > neug_rc_max)
327         neug_rc_max = rct_b;
328    }
329   else
330     {
331       rct_a = sample;
332       rct_b = 1;
333     }
334 }
335
336 static void repetition_count_test_word (uint8_t b0, uint8_t b1,
337                                         uint8_t b2, uint8_t b3)
338 {
339   if (rct_a == b0)
340     rct_b++;
341   else
342     {
343       rct_a = b0;
344       rct_b = 1;
345     }
346
347   if (rct_a == b1)
348     rct_b++;
349   else
350     {
351       rct_a = b1;
352       rct_b = 1;
353     }
354
355   if (rct_a == b2)
356     rct_b++;
357   else
358     {
359       rct_a = b2;
360       rct_b = 1;
361     }
362
363   if (rct_a == b3)
364     rct_b++;
365   else
366     {
367       rct_a = b3;
368       rct_b = 1;
369     }
370
371   if (rct_b >= REPITITION_COUNT_TEST_CUTOFF)
372     noise_source_error (REPETITION_COUNT);
373   if (rct_b > neug_rc_max)
374     neug_rc_max = rct_b;
375 }
376
377 /* Cuttoff = 18, when min-entropy = 4.2, W= 2^-30 */
378 /* With R, qbinom(1-2^-30,64,2^-4.2) */
379 #define ADAPTIVE_PROPORTION_64_TEST_CUTOFF 18
380
381 static uint8_t ap64t_a;
382 static uint8_t ap64t_b;
383 static uint8_t ap64t_s;
384
385 static void adaptive_proportion_64_test (uint8_t sample)
386 {
387   if (ap64t_s++ >= 64)
388     {
389       ap64t_a = sample;
390       ap64t_s = 1;
391       ap64t_b = 0;
392     }
393   else
394     if (ap64t_a == sample)
395       {
396         ap64t_b++;
397         if (ap64t_b > ADAPTIVE_PROPORTION_64_TEST_CUTOFF)
398           noise_source_error (ADAPTIVE_PROPORTION_64);
399         if (ap64t_b > neug_p64_max)
400           neug_p64_max = ap64t_b;
401       }
402 }
403
404 static void adaptive_proportion_64_test_word (uint8_t b0, uint8_t b1,
405                                               uint8_t b2, uint8_t b3)
406 {
407   if (ap64t_s >= 64)
408     {
409       ap64t_a = b0;
410       ap64t_s = 4;
411       ap64t_b = 0;
412     }
413   else
414     {
415       ap64t_s += 4;
416
417       if (ap64t_a == b0)
418         ap64t_b++;
419     }
420
421   if (ap64t_a == b1)
422     ap64t_b++;
423
424   if (ap64t_a == b2)
425     ap64t_b++;
426
427   if (ap64t_a == b3)
428     ap64t_b++;
429
430   if (ap64t_b > ADAPTIVE_PROPORTION_64_TEST_CUTOFF)
431     noise_source_error (ADAPTIVE_PROPORTION_64);
432   if (ap64t_b > neug_p64_max)
433     neug_p64_max = ap64t_b;
434 }
435
436 /* Cuttoff = 315, when min-entropy = 4.2, W= 2^-30 */
437 /* With R, qbinom(1-2^-30,4096,2^-4.2) */
438 #define ADAPTIVE_PROPORTION_4096_TEST_CUTOFF 315
439
440 static uint8_t ap4096t_a;
441 static uint16_t ap4096t_b;
442 static uint16_t ap4096t_s;
443
444 static void adaptive_proportion_4096_test (uint8_t sample)
445 {
446   if (ap4096t_s++ >= 4096)
447     {
448       ap4096t_a = sample;
449       ap4096t_s = 1;
450       ap4096t_b = 0;
451     }
452   else
453     if (ap4096t_a == sample)
454       {
455         ap4096t_b++;
456         if (ap4096t_b > ADAPTIVE_PROPORTION_4096_TEST_CUTOFF)
457           noise_source_error (ADAPTIVE_PROPORTION_4096);
458         if (ap4096t_b > neug_p4k_max)
459           neug_p4k_max = ap4096t_b;
460       }
461 }
462
463 static void adaptive_proportion_4096_test_word (uint8_t b0, uint8_t b1,
464                                                 uint8_t b2, uint8_t b3)
465 {
466   if (ap4096t_s >= 4096)
467     {
468       ap4096t_a = b0;
469       ap4096t_s = 4;
470       ap4096t_b = 0;
471     }
472   else
473     {
474       ap4096t_s += 4;
475
476       if (ap4096t_a == b0)
477         ap4096t_b++;
478     }
479
480   if (ap4096t_a == b1)
481     ap4096t_b++;
482
483   if (ap4096t_a == b2)
484         ap4096t_b++;
485
486   if (ap4096t_a == b3)
487     ap4096t_b++;
488
489   if (ap4096t_b > ADAPTIVE_PROPORTION_4096_TEST_CUTOFF)
490     noise_source_error (ADAPTIVE_PROPORTION_4096);
491   if (ap4096t_b > neug_p4k_max)
492     neug_p4k_max = ap4096t_b;
493 }
494
495
496 static void noise_source_continuous_test (uint8_t noise)
497 {
498   repetition_count_test (noise);
499   adaptive_proportion_64_test (noise);
500   adaptive_proportion_4096_test (noise);
501 }
502
503 static void noise_source_continuous_test_word (uint8_t b0, uint8_t b1,
504                                                uint8_t b2, uint8_t b3)
505 {
506   repetition_count_test_word (b0, b1, b2, b3);
507   adaptive_proportion_64_test_word (b0, b1, b2, b3);
508   adaptive_proportion_4096_test_word (b0, b1, b2, b3);
509 }
510 \f
511 /*
512  * Ring buffer, filled by generator, consumed by neug_get routine.
513  */
514 struct rng_rb {
515   uint32_t *buf;
516   chopstx_mutex_t m;
517   chopstx_cond_t data_available;
518   chopstx_cond_t space_available;
519   uint8_t head, tail;
520   uint8_t size;
521   unsigned int full :1;
522   unsigned int empty :1;
523 };
524
525 static void rb_init (struct rng_rb *rb, uint32_t *p, uint8_t size)
526 {
527   rb->buf = p;
528   rb->size = size;
529   chopstx_mutex_init (&rb->m);
530   chopstx_cond_init (&rb->data_available);
531   chopstx_cond_init (&rb->space_available);
532   rb->head = rb->tail = 0;
533   rb->full = 0;
534   rb->empty = 1;
535 }
536
537 static void rb_add (struct rng_rb *rb, uint32_t v)
538 {
539   rb->buf[rb->tail++] = v;
540   if (rb->tail == rb->size)
541     rb->tail = 0;
542   if (rb->tail == rb->head)
543     rb->full = 1;
544   rb->empty = 0;
545 }
546
547 static uint32_t rb_del (struct rng_rb *rb)
548 {
549   uint32_t v = rb->buf[rb->head++];
550
551   if (rb->head == rb->size)
552     rb->head = 0;
553   if (rb->head == rb->tail)
554     rb->empty = 1;
555   rb->full = 0;
556
557   return v;
558 }
559
560 uint8_t neug_mode;
561 static int rng_should_terminate;
562 static chopstx_t rng_thread;
563
564
565 /**
566  * @brief Random number generation thread.
567  */
568 static void *
569 rng (void *arg)
570 {
571   struct rng_rb *rb = (struct rng_rb *)arg;
572   int mode = neug_mode;
573
574   rng_should_terminate = 0;
575   chopstx_mutex_init (&mode_mtx);
576   chopstx_cond_init (&mode_cond);
577
578   /* Enable ADCs */
579   adc_start ();
580
581   ep_init (mode);
582   while (!rng_should_terminate)
583     {
584       int err;
585       int n;
586
587       err = adc_wait_completion ();
588
589       chopstx_mutex_lock (&mode_mtx);
590       if (err || mode != neug_mode)
591         {
592           mode = neug_mode;
593
594           noise_source_cnt_max_reset ();
595
596           /* Discarding data available, re-initiate from the start.  */
597           ep_init (mode);
598           chopstx_cond_signal (&mode_cond);
599           chopstx_mutex_unlock (&mode_mtx);
600           continue;
601         }
602       else
603         chopstx_mutex_unlock (&mode_mtx);
604
605       if ((n = ep_process (mode)))
606         {
607           int i;
608           const uint32_t *vp;
609
610           if (neug_err_state != 0
611               && (mode == NEUG_MODE_CONDITIONED || mode == NEUG_MODE_RAW))
612             {
613               /* Don't use the result and do it again.  */
614               noise_source_error_reset ();
615               continue;
616             }
617
618           vp = ep_output (mode);
619
620           chopstx_mutex_lock (&rb->m);
621           while (rb->full)
622             chopstx_cond_wait (&rb->space_available, &rb->m);
623
624           for (i = 0; i < n; i++)
625             {
626               rb_add (rb, *vp++);
627               if (rb->full)
628                 break;
629             }
630
631           chopstx_cond_signal (&rb->data_available);
632           chopstx_mutex_unlock (&rb->m);
633         }
634     }
635
636   adc_stop ();
637
638   return NULL;
639 }
640
641 static struct rng_rb the_ring_buffer;
642
643 extern uint8_t __process2_stack_base__, __process2_stack_size__;
644 const uint32_t __stackaddr_rng = (uint32_t)&__process2_stack_base__;
645 const size_t __stacksize_rng = (size_t)&__process2_stack_size__;
646 #define PRIO_RNG 2
647
648 /**
649  * @brief Initialize NeuG.
650  */
651 void
652 neug_init (uint32_t *buf, uint8_t size)
653 {
654   const uint32_t *u = (const uint32_t *)unique_device_id ();
655   struct rng_rb *rb = &the_ring_buffer;
656   int i;
657
658   RCC->AHBENR |= RCC_AHBENR_CRCEN;
659   CRC->CR = CRC_CR_RESET;
660
661   /*
662    * This initialization ensures that it generates different sequence
663    * even if all physical conditions are same.
664    */
665   for (i = 0; i < 3; i++)
666     CRC->DR = *u++;
667
668   neug_mode = NEUG_MODE_CONDITIONED;
669   rb_init (rb, buf, size);
670
671   rng_thread = chopstx_create (PRIO_RNG, __stackaddr_rng, __stacksize_rng,
672                                rng, rb);
673 }
674
675 /**
676  * @breif Flush random bytes.
677  */
678 void
679 neug_flush (void)
680 {
681   struct rng_rb *rb = &the_ring_buffer;
682
683   chopstx_mutex_lock (&rb->m);
684   while (!rb->empty)
685     (void)rb_del (rb);
686   chopstx_cond_signal (&rb->space_available);
687   chopstx_mutex_unlock (&rb->m);
688 }
689
690
691 /**
692  * @brief  Wakes up RNG thread to generate random numbers.
693  */
694 void
695 neug_kick_filling (void)
696 {
697   struct rng_rb *rb = &the_ring_buffer;
698
699   chopstx_mutex_lock (&rb->m);
700   if (!rb->full)
701     chopstx_cond_signal (&rb->space_available);
702   chopstx_mutex_unlock (&rb->m);
703 }
704
705 /**
706  * @brief  Get random word (32-bit) from NeuG.
707  * @detail With NEUG_KICK_FILLING, it wakes up RNG thread.
708  *         With NEUG_NO_KICK, it doesn't wake up RNG thread automatically,
709  *         it is needed to call neug_kick_filling later.
710  */
711 uint32_t
712 neug_get (int kick)
713 {
714   struct rng_rb *rb = &the_ring_buffer;
715   uint32_t v;
716
717   chopstx_mutex_lock (&rb->m);
718   while (rb->empty)
719     chopstx_cond_wait (&rb->data_available, &rb->m);
720   v = rb_del (rb);
721   if (kick)
722     chopstx_cond_signal (&rb->space_available);
723   chopstx_mutex_unlock (&rb->m);
724
725   return v;
726 }
727
728 int
729 neug_get_nonblock (uint32_t *p)
730 {
731   struct rng_rb *rb = &the_ring_buffer;
732   int r = 0;
733
734   chopstx_mutex_lock (&rb->m);
735   if (rb->empty)
736     {
737       r = -1;
738       chopstx_cond_signal (&rb->space_available);
739     }
740   else
741     *p = rb_del (rb);
742   chopstx_mutex_unlock (&rb->m);
743
744   return r;
745 }
746
747 int neug_consume_random (void (*proc) (uint32_t, int))
748 {
749   int i = 0;
750   struct rng_rb *rb = &the_ring_buffer;
751
752   chopstx_mutex_lock (&rb->m);
753   while (!rb->empty)
754     {
755       uint32_t v;
756
757       v = rb_del (rb);
758       proc (v, i);
759       i++;
760     }
761   chopstx_cond_signal (&rb->space_available);
762   chopstx_mutex_unlock (&rb->m);
763
764   return i;
765 }
766
767 void
768 neug_wait_full (void)
769 {
770   struct rng_rb *rb = &the_ring_buffer;
771
772   chopstx_mutex_lock (&rb->m);
773   while (!rb->full)
774     chopstx_cond_wait (&rb->data_available, &rb->m);
775   chopstx_mutex_unlock (&rb->m);
776 }
777
778 void
779 neug_fini (void)
780 {
781   rng_should_terminate = 1;
782   neug_get (1);
783   chopstx_join (rng_thread, NULL);
784 }
785
786 void
787 neug_mode_select (uint8_t mode)
788 {
789   if (neug_mode == mode)
790     return;
791
792   neug_wait_full ();
793
794   chopstx_mutex_lock (&mode_mtx);
795   neug_mode = mode;
796   neug_flush ();
797   chopstx_cond_wait (&mode_cond, &mode_mtx);
798   chopstx_mutex_unlock (&mode_mtx);
799
800   neug_wait_full ();
801   neug_flush ();
802 }