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