xref: /freebsd/sys/dev/random/unit_test.c (revision a812392203d7c4c3f0db9d8a0f3391374c49c71f)
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 }
258