]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/random/unit_test.c
Merge sync of head
[FreeBSD/FreeBSD.git] / sys / dev / random / unit_test.c
1 /*-
2  * Copyright (c) 2000-2013 Mark R V Murray
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 /*
30  Build this by going:
31
32 cc -g -O0 -pthread -DRANDOM_<alg> -DRANDOM_DEBUG -I../.. -lstdthreads -Wall \
33         unit_test.c \
34         yarrow.c \
35         fortuna.c \
36         hash.c \
37         ../../crypto/rijndael/rijndael-api-fst.c \
38         ../../crypto/rijndael/rijndael-alg-fst.c \
39         ../../crypto/sha2/sha2.c \
40         -o unit_test
41 ./unit_test
42
43 Where <alg> is YARROW or FORTUNA.
44 */
45
46 #include <sys/types.h>
47 #include <inttypes.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <threads.h>
51 #include <unistd.h>
52
53 #include "unit_test.h"
54
55 #ifdef RANDOM_YARROW
56 #include "dev/random/yarrow.h"
57 #endif
58 #ifdef RANDOM_FORTUNA
59 #include "dev/random/fortuna.h"
60 #endif
61
62 #define NUM_THREADS       3
63
64 static volatile int stopseeding = 0;
65
66 void
67 random_adaptor_unblock(void)
68 {
69
70 #if 0
71         if (mtx_trylock(&random_reseed_mtx) == thrd_busy)
72                 printf("Mutex held. Good.\n");
73         else {
74                 printf("Mutex not held. PANIC!!\n");
75                 thrd_exit(0);
76         }
77 #endif
78         printf("random: unblocking device.\n");
79 }
80
81 static int
82 RunHarvester(void *arg __unused)
83 {
84         int i, r;
85         struct harvest_event e;
86
87         for (i = 0; ; i++) {
88                 if (stopseeding)
89                         break;
90                 if (i % 1000 == 0)
91                         printf("Harvest: %d\n", i);
92                 r = random()%10;
93                 e.he_somecounter = i;
94                 *((uint64_t *)e.he_entropy) = random();
95                 e.he_size = 8;
96                 e.he_bits = random()%4;
97                 e.he_destination = i;
98                 e.he_source = (i + 3)%7;
99                 e.he_next = NULL;
100 #ifdef RANDOM_YARROW
101                 random_yarrow_process_event(&e);
102 #endif
103 #ifdef RANDOM_FORTUNA
104                 random_fortuna_process_event(&e);
105 #endif
106                 usleep(r);
107         }
108
109         printf("Thread #0 ends\n");
110
111         thrd_exit(0);
112
113         return (0);
114 }
115
116 static int
117 WriteCSPRNG(void *threadid)
118 {
119         uint8_t *buf;
120         int i;
121
122         printf("Thread #1 starts\n");
123
124         for (i = 0; ; i++) {
125                 if (stopseeding)
126                         break;
127                 buf = malloc(4096);
128                 if (i % 1000 == 0)
129                         printf("Thread write 1 - %d\n", i);
130                 if (buf != NULL) {
131 #ifdef RANDOM_YARROW
132                         random_yarrow_write(buf, i);
133 #endif
134 #ifdef RANDOM_FORTUNA
135                         random_fortuna_write(buf, i);
136 #endif
137                         free(buf);
138                 }
139                 usleep(1000000);
140         }
141
142         printf("Thread #1 ends\n");
143
144         thrd_exit(0);
145
146         return (0);
147 }
148
149 static int
150 ReadCSPRNG(void *threadid)
151 {
152         size_t tid;
153         uint8_t *buf;
154         int i;
155
156         tid = (size_t)threadid;
157         printf("Thread #%zd starts\n", tid);
158
159 #ifdef RANDOM_YARROW
160         while (!random_yarrow_seeded())
161 #endif
162 #ifdef RANDOM_FORTUNA
163         while (!random_fortuna_seeded())
164 #endif
165         {
166 #ifdef RANDOM_YARROW
167                 random_yarrow_read(NULL, 0);
168                 random_yarrow_read(NULL, 1);
169 #endif
170 #ifdef RANDOM_FORTUNA
171                 random_fortuna_read(NULL, 0);
172                 random_fortuna_read(NULL, 1);
173 #endif
174                 usleep(100);
175         }
176
177         for (i = 0; i < 100000; i++) {
178                 buf = malloc(i);
179                 if (i % 1000 == 0)
180                         printf("Thread read %zd - %d %p\n", tid, i, buf);
181                 if (buf != NULL) {
182 #ifdef RANDOM_YARROW
183                         random_yarrow_read(NULL, 0);
184                         random_yarrow_read(buf, i);
185                         random_yarrow_read(NULL, 1);
186 #endif
187 #ifdef RANDOM_FORTUNA
188                         random_fortuna_read(NULL, 0);
189                         random_fortuna_read(buf, i);
190                         random_fortuna_read(NULL, 1);
191 #endif
192 #if 0
193                         {
194                         int j;
195
196                         for (j = 0; j < i; j++) {
197                                 printf(" %02X", buf[j]);
198                                 if (j % 32 == 31 || j == i - 1)
199                                         printf("\n");
200                         }
201                         }
202 #endif
203                         free(buf);
204                 }
205                 usleep(100);
206         }
207
208         printf("Thread #%zd ends\n", tid);
209
210         thrd_exit(0);
211
212         return (0);
213 }
214
215 int
216 main(int argc, char *argv[])
217 {
218         thrd_t threads[NUM_THREADS];
219         int rc;
220         long t;
221
222 #ifdef RANDOM_YARROW
223         random_yarrow_init_alg();
224 #endif
225 #ifdef RANDOM_FORTUNA
226         random_fortuna_init_alg();
227 #endif
228
229         for (t = 0; t < NUM_THREADS; t++) {
230                 printf("In main: creating thread %ld\n", t);
231                 rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : (t == 1 ? WriteCSPRNG : ReadCSPRNG)), t);
232                 if (rc != thrd_success) {
233                         printf("ERROR; return code from thrd_create() is %d\n", rc);
234                         exit(-1);
235                 }
236         }
237
238         for (t = 2; t < NUM_THREADS; t++)
239                 thrd_join(threads[t], &rc);
240
241         stopseeding = 1;
242
243         thrd_join(threads[1], &rc);
244         thrd_join(threads[0], &rc);
245
246 #ifdef RANDOM_YARROW
247         random_yarrow_deinit_alg();
248 #endif
249 #ifdef RANDOM_FORTUNA
250         random_fortuna_deinit_alg();
251 #endif
252
253         /* Last thing that main() should do */
254         thrd_exit(0);
255
256         return (0);
257 }