xref: /freebsd-14.2/sys/dev/random/unit_test.c (revision d1b06863)
110cb2424SMark Murray /*-
2*d1b06863SMark Murray  * Copyright (c) 2000-2015 Mark R V Murray
310cb2424SMark Murray  * All rights reserved.
410cb2424SMark Murray  *
510cb2424SMark Murray  * Redistribution and use in source and binary forms, with or without
610cb2424SMark Murray  * modification, are permitted provided that the following conditions
710cb2424SMark Murray  * are met:
810cb2424SMark Murray  * 1. Redistributions of source code must retain the above copyright
910cb2424SMark Murray  *    notice, this list of conditions and the following disclaimer
1010cb2424SMark Murray  *    in this position and unchanged.
1110cb2424SMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
1210cb2424SMark Murray  *    notice, this list of conditions and the following disclaimer in the
1310cb2424SMark Murray  *    documentation and/or other materials provided with the distribution.
1410cb2424SMark Murray  *
1510cb2424SMark Murray  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1610cb2424SMark Murray  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1710cb2424SMark Murray  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1810cb2424SMark Murray  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1910cb2424SMark Murray  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2010cb2424SMark Murray  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2110cb2424SMark Murray  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2210cb2424SMark Murray  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2310cb2424SMark Murray  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2410cb2424SMark Murray  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2510cb2424SMark Murray  *
2610cb2424SMark Murray  * $FreeBSD$
2710cb2424SMark Murray  */
2810cb2424SMark Murray 
2910cb2424SMark Murray /*
3010cb2424SMark Murray  Build this by going:
3110cb2424SMark Murray 
3210cb2424SMark Murray cc -g -O0 -pthread -DRANDOM_<alg> -DRANDOM_DEBUG -I../.. -lstdthreads -Wall \
3310cb2424SMark Murray 	unit_test.c \
3410cb2424SMark Murray 	yarrow.c \
3510cb2424SMark Murray 	fortuna.c \
3610cb2424SMark Murray 	hash.c \
3710cb2424SMark Murray 	../../crypto/rijndael/rijndael-api-fst.c \
3810cb2424SMark Murray 	../../crypto/rijndael/rijndael-alg-fst.c \
3910cb2424SMark Murray 	../../crypto/sha2/sha2.c \
40*d1b06863SMark Murray         -lz \
4110cb2424SMark Murray 	-o unit_test
4210cb2424SMark Murray ./unit_test
4310cb2424SMark Murray 
4410cb2424SMark Murray Where <alg> is YARROW or FORTUNA.
4510cb2424SMark Murray */
4610cb2424SMark Murray 
4710cb2424SMark Murray #include <sys/types.h>
4810cb2424SMark Murray #include <inttypes.h>
4910cb2424SMark Murray #include <stdio.h>
5010cb2424SMark Murray #include <stdlib.h>
5110cb2424SMark Murray #include <threads.h>
5210cb2424SMark Murray #include <unistd.h>
53*d1b06863SMark Murray #include <zlib.h>
5410cb2424SMark Murray 
5510cb2424SMark Murray #include "unit_test.h"
5610cb2424SMark Murray 
5710cb2424SMark Murray #ifdef RANDOM_YARROW
5810cb2424SMark Murray #include "dev/random/yarrow.h"
5910cb2424SMark Murray #endif
6010cb2424SMark Murray #ifdef RANDOM_FORTUNA
6110cb2424SMark Murray #include "dev/random/fortuna.h"
6210cb2424SMark Murray #endif
6310cb2424SMark Murray 
6410cb2424SMark Murray #define	NUM_THREADS	  3
65*d1b06863SMark Murray #define	DEBUG
6610cb2424SMark Murray 
6710cb2424SMark Murray static volatile int stopseeding = 0;
6810cb2424SMark Murray 
69*d1b06863SMark Murray static __inline void
70*d1b06863SMark Murray check_err(int err, const char *func)
71*d1b06863SMark Murray {
72*d1b06863SMark Murray 	if (err != Z_OK) {
73*d1b06863SMark Murray 		fprintf(stderr, "Compress error in %s: %d\n", func, err);
74*d1b06863SMark Murray 		exit(0);
75*d1b06863SMark Murray 	}
76*d1b06863SMark Murray }
77*d1b06863SMark Murray 
78*d1b06863SMark Murray void *
79*d1b06863SMark Murray myalloc(void *q, unsigned n, unsigned m)
80*d1b06863SMark Murray {
81*d1b06863SMark Murray 	q = Z_NULL;
82*d1b06863SMark Murray 	return (calloc(n, m));
83*d1b06863SMark Murray }
84*d1b06863SMark Murray 
85*d1b06863SMark Murray void myfree(void *q, void *p)
86*d1b06863SMark Murray {
87*d1b06863SMark Murray 	q = Z_NULL;
88*d1b06863SMark Murray 	free(p);
89*d1b06863SMark Murray }
90*d1b06863SMark Murray 
91*d1b06863SMark Murray size_t
92*d1b06863SMark Murray block_deflate(uint8_t *uncompr, uint8_t *compr, const size_t len)
93*d1b06863SMark Murray {
94*d1b06863SMark Murray 	z_stream c_stream;
95*d1b06863SMark Murray 	int err;
96*d1b06863SMark Murray 
97*d1b06863SMark Murray 	if (len == 0)
98*d1b06863SMark Murray 		return (0);
99*d1b06863SMark Murray 
100*d1b06863SMark Murray 	c_stream.zalloc = myalloc;
101*d1b06863SMark Murray 	c_stream.zfree = myfree;
102*d1b06863SMark Murray 	c_stream.opaque = NULL;
103*d1b06863SMark Murray 
104*d1b06863SMark Murray 	err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
105*d1b06863SMark Murray 	check_err(err, "deflateInit");
106*d1b06863SMark Murray 
107*d1b06863SMark Murray 	c_stream.next_in  = uncompr;
108*d1b06863SMark Murray 	c_stream.next_out = compr;
109*d1b06863SMark Murray 	c_stream.avail_in = len;
110*d1b06863SMark Murray 	c_stream.avail_out = len*2u +512u;
111*d1b06863SMark Murray 
112*d1b06863SMark Murray 	while (c_stream.total_in != len && c_stream.total_out < (len*2u + 512u)) {
113*d1b06863SMark Murray 		err = deflate(&c_stream, Z_NO_FLUSH);
114*d1b06863SMark Murray #ifdef DEBUG
115*d1b06863SMark Murray 		printf("deflate: len = %zd  total_in = %lu  total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
116*d1b06863SMark Murray #endif
117*d1b06863SMark Murray 		check_err(err, "deflate(..., Z_NO_FLUSH)");
118*d1b06863SMark Murray 	}
119*d1b06863SMark Murray 
120*d1b06863SMark Murray 	for (;;) {
121*d1b06863SMark Murray 		err = deflate(&c_stream, Z_FINISH);
122*d1b06863SMark Murray #ifdef DEBUG
123*d1b06863SMark Murray 		printf("deflate: len = %zd  total_in = %lu  total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
124*d1b06863SMark Murray #endif
125*d1b06863SMark Murray 		if (err == Z_STREAM_END) break;
126*d1b06863SMark Murray 		check_err(err, "deflate(..., Z_STREAM_END)");
127*d1b06863SMark Murray 	}
128*d1b06863SMark Murray 
129*d1b06863SMark Murray 	err = deflateEnd(&c_stream);
130*d1b06863SMark Murray 	check_err(err, "deflateEnd");
131*d1b06863SMark Murray 
132*d1b06863SMark Murray 	return ((size_t)c_stream.total_out);
133*d1b06863SMark Murray }
134*d1b06863SMark Murray 
13510cb2424SMark Murray void
13610cb2424SMark Murray random_adaptor_unblock(void)
13710cb2424SMark Murray {
13810cb2424SMark Murray 
13910cb2424SMark Murray #if 0
14010cb2424SMark Murray 	if (mtx_trylock(&random_reseed_mtx) == thrd_busy)
14110cb2424SMark Murray 		printf("Mutex held. Good.\n");
14210cb2424SMark Murray 	else {
14310cb2424SMark Murray 		printf("Mutex not held. PANIC!!\n");
14410cb2424SMark Murray 		thrd_exit(0);
14510cb2424SMark Murray 	}
14610cb2424SMark Murray #endif
14710cb2424SMark Murray 	printf("random: unblocking device.\n");
14810cb2424SMark Murray }
14910cb2424SMark Murray 
15010cb2424SMark Murray static int
15110cb2424SMark Murray RunHarvester(void *arg __unused)
15210cb2424SMark Murray {
15310cb2424SMark Murray 	int i, r;
15410cb2424SMark Murray 	struct harvest_event e;
15510cb2424SMark Murray 
15610cb2424SMark Murray 	for (i = 0; ; i++) {
15710cb2424SMark Murray 		if (stopseeding)
15810cb2424SMark Murray 			break;
15910cb2424SMark Murray 		if (i % 1000 == 0)
16010cb2424SMark Murray 			printf("Harvest: %d\n", i);
16110cb2424SMark Murray 		r = random()%10;
16210cb2424SMark Murray 		e.he_somecounter = i;
16310cb2424SMark Murray 		*((uint64_t *)e.he_entropy) = random();
16410cb2424SMark Murray 		e.he_size = 8;
16510cb2424SMark Murray 		e.he_bits = random()%4;
16610cb2424SMark Murray 		e.he_destination = i;
16710cb2424SMark Murray 		e.he_source = (i + 3)%7;
16810cb2424SMark Murray 		e.he_next = NULL;
16910cb2424SMark Murray #ifdef RANDOM_YARROW
17010cb2424SMark Murray 		random_yarrow_process_event(&e);
17110cb2424SMark Murray #endif
17210cb2424SMark Murray #ifdef RANDOM_FORTUNA
17310cb2424SMark Murray 		random_fortuna_process_event(&e);
17410cb2424SMark Murray #endif
17510cb2424SMark Murray 		usleep(r);
17610cb2424SMark Murray 	}
17710cb2424SMark Murray 
17810cb2424SMark Murray 	printf("Thread #0 ends\n");
17910cb2424SMark Murray 
18010cb2424SMark Murray 	thrd_exit(0);
18110cb2424SMark Murray 
18210cb2424SMark Murray 	return (0);
18310cb2424SMark Murray }
18410cb2424SMark Murray 
18510cb2424SMark Murray static int
18610cb2424SMark Murray WriteCSPRNG(void *threadid)
18710cb2424SMark Murray {
18810cb2424SMark Murray 	uint8_t *buf;
18910cb2424SMark Murray 	int i;
19010cb2424SMark Murray 
19110cb2424SMark Murray 	printf("Thread #1 starts\n");
19210cb2424SMark Murray 
19310cb2424SMark Murray 	for (i = 0; ; i++) {
19410cb2424SMark Murray 		if (stopseeding)
19510cb2424SMark Murray 			break;
19610cb2424SMark Murray 		buf = malloc(4096);
19710cb2424SMark Murray 		if (i % 1000 == 0)
19810cb2424SMark Murray 			printf("Thread write 1 - %d\n", i);
19910cb2424SMark Murray 		if (buf != NULL) {
200*d1b06863SMark Murray 			printf("Thread 1 writing.\n");
20110cb2424SMark Murray #ifdef RANDOM_YARROW
20210cb2424SMark Murray 			random_yarrow_write(buf, i);
20310cb2424SMark Murray #endif
20410cb2424SMark Murray #ifdef RANDOM_FORTUNA
20510cb2424SMark Murray 			random_fortuna_write(buf, i);
20610cb2424SMark Murray #endif
20710cb2424SMark Murray 			free(buf);
20810cb2424SMark Murray 		}
20910cb2424SMark Murray 		usleep(1000000);
21010cb2424SMark Murray 	}
21110cb2424SMark Murray 
21210cb2424SMark Murray 	printf("Thread #1 ends\n");
21310cb2424SMark Murray 
21410cb2424SMark Murray 	thrd_exit(0);
21510cb2424SMark Murray 
21610cb2424SMark Murray 	return (0);
21710cb2424SMark Murray }
21810cb2424SMark Murray 
21910cb2424SMark Murray static int
22010cb2424SMark Murray ReadCSPRNG(void *threadid)
22110cb2424SMark Murray {
222*d1b06863SMark Murray 	size_t tid, zsize;
223*d1b06863SMark Murray 	uint8_t *buf, *zbuf;
22410cb2424SMark Murray 	int i;
225*d1b06863SMark Murray #ifdef DEBUG
226*d1b06863SMark Murray 	int j;
227*d1b06863SMark Murray #endif
22810cb2424SMark Murray 
22910cb2424SMark Murray 	tid = (size_t)threadid;
23010cb2424SMark Murray 	printf("Thread #%zd starts\n", tid);
23110cb2424SMark Murray 
23210cb2424SMark Murray #ifdef RANDOM_YARROW
23310cb2424SMark Murray 	while (!random_yarrow_seeded())
23410cb2424SMark Murray #endif
23510cb2424SMark Murray #ifdef RANDOM_FORTUNA
23610cb2424SMark Murray 	while (!random_fortuna_seeded())
23710cb2424SMark Murray #endif
23810cb2424SMark Murray 	{
23910cb2424SMark Murray #ifdef RANDOM_YARROW
240*d1b06863SMark Murray 		random_yarrow_pre_read();
241*d1b06863SMark Murray 		random_yarrow_post_read();
24210cb2424SMark Murray #endif
24310cb2424SMark Murray #ifdef RANDOM_FORTUNA
244*d1b06863SMark Murray 		random_fortuna_pre_read();
245*d1b06863SMark Murray 		random_fortuna_post_read();
24610cb2424SMark Murray #endif
24710cb2424SMark Murray 		usleep(100);
24810cb2424SMark Murray 	}
24910cb2424SMark Murray 
25010cb2424SMark Murray 	for (i = 0; i < 100000; i++) {
25110cb2424SMark Murray 		buf = malloc(i);
252*d1b06863SMark Murray 		zbuf = malloc(2*i + 1024);
25310cb2424SMark Murray 		if (i % 1000 == 0)
254*d1b06863SMark Murray 			printf("Thread read %zd - %d\n", tid, i);
255*d1b06863SMark Murray 		if (buf != NULL && zbuf != NULL) {
25610cb2424SMark Murray #ifdef RANDOM_YARROW
257*d1b06863SMark Murray 			random_yarrow_pre_read();
25810cb2424SMark Murray 			random_yarrow_read(buf, i);
259*d1b06863SMark Murray 			random_yarrow_post_read();
26010cb2424SMark Murray #endif
26110cb2424SMark Murray #ifdef RANDOM_FORTUNA
262*d1b06863SMark Murray 			random_fortuna_pre_read();
26310cb2424SMark Murray 			random_fortuna_read(buf, i);
264*d1b06863SMark Murray 			random_fortuna_post_read();
26510cb2424SMark Murray #endif
266*d1b06863SMark Murray 			zsize = block_deflate(buf, zbuf, i);
267*d1b06863SMark Murray 			if (zsize < i)
268*d1b06863SMark Murray 				printf("ERROR!! Compressible RNG output!\n");
269*d1b06863SMark Murray #ifdef DEBUG
270*d1b06863SMark Murray 			printf("RNG output:\n");
27110cb2424SMark Murray 			for (j = 0; j < i; j++) {
27210cb2424SMark Murray 				printf(" %02X", buf[j]);
27310cb2424SMark Murray 				if (j % 32 == 31 || j == i - 1)
27410cb2424SMark Murray 					printf("\n");
27510cb2424SMark Murray 			}
276*d1b06863SMark Murray 			printf("Compressed output:\n");
277*d1b06863SMark Murray 			for (j = 0; j < zsize; j++) {
278*d1b06863SMark Murray 				printf(" %02X", zbuf[j]);
279*d1b06863SMark Murray 				if (j % 32 == 31 || j == zsize - 1)
280*d1b06863SMark Murray 					printf("\n");
28110cb2424SMark Murray 			}
28210cb2424SMark Murray #endif
283*d1b06863SMark Murray 			free(zbuf);
28410cb2424SMark Murray 			free(buf);
28510cb2424SMark Murray 		}
28610cb2424SMark Murray 		usleep(100);
28710cb2424SMark Murray 	}
28810cb2424SMark Murray 
28910cb2424SMark Murray 	printf("Thread #%zd ends\n", tid);
29010cb2424SMark Murray 
29110cb2424SMark Murray 	thrd_exit(0);
29210cb2424SMark Murray 
29310cb2424SMark Murray 	return (0);
29410cb2424SMark Murray }
29510cb2424SMark Murray 
29610cb2424SMark Murray int
29710cb2424SMark Murray main(int argc, char *argv[])
29810cb2424SMark Murray {
29910cb2424SMark Murray 	thrd_t threads[NUM_THREADS];
30010cb2424SMark Murray 	int rc;
30110cb2424SMark Murray 	long t;
30210cb2424SMark Murray 
30310cb2424SMark Murray #ifdef RANDOM_YARROW
30410cb2424SMark Murray 	random_yarrow_init_alg();
30510cb2424SMark Murray #endif
30610cb2424SMark Murray #ifdef RANDOM_FORTUNA
30710cb2424SMark Murray 	random_fortuna_init_alg();
30810cb2424SMark Murray #endif
30910cb2424SMark Murray 
31010cb2424SMark Murray 	for (t = 0; t < NUM_THREADS; t++) {
31110cb2424SMark Murray 		printf("In main: creating thread %ld\n", t);
312*d1b06863SMark Murray 		rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : (t == 1 ? WriteCSPRNG : ReadCSPRNG)), NULL);
31310cb2424SMark Murray 		if (rc != thrd_success) {
31410cb2424SMark Murray 			printf("ERROR; return code from thrd_create() is %d\n", rc);
31510cb2424SMark Murray 			exit(-1);
31610cb2424SMark Murray 		}
31710cb2424SMark Murray 	}
31810cb2424SMark Murray 
31910cb2424SMark Murray 	for (t = 2; t < NUM_THREADS; t++)
32010cb2424SMark Murray 		thrd_join(threads[t], &rc);
32110cb2424SMark Murray 
32210cb2424SMark Murray 	stopseeding = 1;
32310cb2424SMark Murray 
32410cb2424SMark Murray 	thrd_join(threads[1], &rc);
32510cb2424SMark Murray 	thrd_join(threads[0], &rc);
32610cb2424SMark Murray 
32710cb2424SMark Murray #ifdef RANDOM_YARROW
32810cb2424SMark Murray 	random_yarrow_deinit_alg();
32910cb2424SMark Murray #endif
33010cb2424SMark Murray #ifdef RANDOM_FORTUNA
33110cb2424SMark Murray 	random_fortuna_deinit_alg();
33210cb2424SMark Murray #endif
33310cb2424SMark Murray 
33410cb2424SMark Murray 	/* Last thing that main() should do */
33510cb2424SMark Murray 	thrd_exit(0);
33610cb2424SMark Murray 
33710cb2424SMark Murray 	return (0);
33810cb2424SMark Murray }
339