110cb2424SMark Murray /*-
2d1b06863SMark 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
2710cb2424SMark Murray /*
2810cb2424SMark Murray Build this by going:
2910cb2424SMark Murray
30e866d8f0SMark Murray cc -g -O0 -pthread -DRANDOM_<alg> -I../.. -lstdthreads -Wall \
3110cb2424SMark Murray unit_test.c \
3210cb2424SMark Murray fortuna.c \
3310cb2424SMark Murray hash.c \
3410cb2424SMark Murray ../../crypto/rijndael/rijndael-api-fst.c \
3510cb2424SMark Murray ../../crypto/rijndael/rijndael-alg-fst.c \
367a3f5d11SAllan Jude ../../crypto/sha2/sha256c.c \
37d1b06863SMark Murray -lz \
3810cb2424SMark Murray -o unit_test
3910cb2424SMark Murray ./unit_test
4010cb2424SMark Murray
41*19fa89e9SMark Murray Where <alg> is FORTUNA. The parameterisation is a leftover from
42*19fa89e9SMark Murray when Yarrow was an option, and remains to enable the testing of
43*19fa89e9SMark Murray possible future algorithms.
4410cb2424SMark Murray */
4510cb2424SMark Murray
4610cb2424SMark Murray #include <sys/types.h>
4710cb2424SMark Murray #include <inttypes.h>
48646041a8SMark Murray #include <stdbool.h>
4910cb2424SMark Murray #include <stdio.h>
5010cb2424SMark Murray #include <stdlib.h>
5110cb2424SMark Murray #include <threads.h>
5210cb2424SMark Murray #include <unistd.h>
53d1b06863SMark Murray #include <zlib.h>
5410cb2424SMark Murray
553aa77530SMark Murray #include "randomdev.h"
5610cb2424SMark Murray #include "unit_test.h"
5710cb2424SMark Murray
5810cb2424SMark Murray #define NUM_THREADS 3
59d1b06863SMark Murray #define DEBUG
6010cb2424SMark Murray
6110cb2424SMark Murray static volatile int stopseeding = 0;
6210cb2424SMark Murray
63d1b06863SMark Murray static __inline void
check_err(int err,const char * func)64d1b06863SMark Murray check_err(int err, const char *func)
65d1b06863SMark Murray {
66d1b06863SMark Murray if (err != Z_OK) {
67d1b06863SMark Murray fprintf(stderr, "Compress error in %s: %d\n", func, err);
68d1b06863SMark Murray exit(0);
69d1b06863SMark Murray }
70d1b06863SMark Murray }
71d1b06863SMark Murray
72d1b06863SMark Murray void *
myalloc(void * q,unsigned n,unsigned m)73d1b06863SMark Murray myalloc(void *q, unsigned n, unsigned m)
74d1b06863SMark Murray {
75d1b06863SMark Murray q = Z_NULL;
76d1b06863SMark Murray return (calloc(n, m));
77d1b06863SMark Murray }
78d1b06863SMark Murray
myfree(void * q,void * p)79d1b06863SMark Murray void myfree(void *q, void *p)
80d1b06863SMark Murray {
81d1b06863SMark Murray q = Z_NULL;
82d1b06863SMark Murray free(p);
83d1b06863SMark Murray }
84d1b06863SMark Murray
85d1b06863SMark Murray size_t
block_deflate(uint8_t * uncompr,uint8_t * compr,const size_t len)86d1b06863SMark Murray block_deflate(uint8_t *uncompr, uint8_t *compr, const size_t len)
87d1b06863SMark Murray {
88d1b06863SMark Murray z_stream c_stream;
89d1b06863SMark Murray int err;
90d1b06863SMark Murray
91d1b06863SMark Murray if (len == 0)
92d1b06863SMark Murray return (0);
93d1b06863SMark Murray
94d1b06863SMark Murray c_stream.zalloc = myalloc;
95d1b06863SMark Murray c_stream.zfree = myfree;
96d1b06863SMark Murray c_stream.opaque = NULL;
97d1b06863SMark Murray
98d1b06863SMark Murray err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
99d1b06863SMark Murray check_err(err, "deflateInit");
100d1b06863SMark Murray
101d1b06863SMark Murray c_stream.next_in = uncompr;
102d1b06863SMark Murray c_stream.next_out = compr;
103d1b06863SMark Murray c_stream.avail_in = len;
104d1b06863SMark Murray c_stream.avail_out = len*2u +512u;
105d1b06863SMark Murray
106d1b06863SMark Murray while (c_stream.total_in != len && c_stream.total_out < (len*2u + 512u)) {
107d1b06863SMark Murray err = deflate(&c_stream, Z_NO_FLUSH);
108d1b06863SMark Murray #ifdef DEBUG
1093aa77530SMark Murray printf("deflate progress: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
110d1b06863SMark Murray #endif
111d1b06863SMark Murray check_err(err, "deflate(..., Z_NO_FLUSH)");
112d1b06863SMark Murray }
113d1b06863SMark Murray
114d1b06863SMark Murray for (;;) {
115d1b06863SMark Murray err = deflate(&c_stream, Z_FINISH);
116d1b06863SMark Murray #ifdef DEBUG
1173aa77530SMark Murray printf("deflate final: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out);
118d1b06863SMark Murray #endif
119d1b06863SMark Murray if (err == Z_STREAM_END) break;
120d1b06863SMark Murray check_err(err, "deflate(..., Z_STREAM_END)");
121d1b06863SMark Murray }
122d1b06863SMark Murray
123d1b06863SMark Murray err = deflateEnd(&c_stream);
124d1b06863SMark Murray check_err(err, "deflateEnd");
125d1b06863SMark Murray
126d1b06863SMark Murray return ((size_t)c_stream.total_out);
127d1b06863SMark Murray }
128d1b06863SMark Murray
12910cb2424SMark Murray void
randomdev_unblock(void)1303aa77530SMark Murray randomdev_unblock(void)
13110cb2424SMark Murray {
13210cb2424SMark Murray
13310cb2424SMark Murray #if 0
13410cb2424SMark Murray if (mtx_trylock(&random_reseed_mtx) == thrd_busy)
13510cb2424SMark Murray printf("Mutex held. Good.\n");
13610cb2424SMark Murray else {
13710cb2424SMark Murray printf("Mutex not held. PANIC!!\n");
13810cb2424SMark Murray thrd_exit(0);
13910cb2424SMark Murray }
14010cb2424SMark Murray #endif
14110cb2424SMark Murray printf("random: unblocking device.\n");
14210cb2424SMark Murray }
14310cb2424SMark Murray
14410cb2424SMark Murray static int
RunHarvester(void * arg __unused)14510cb2424SMark Murray RunHarvester(void *arg __unused)
14610cb2424SMark Murray {
14710cb2424SMark Murray int i, r;
14810cb2424SMark Murray struct harvest_event e;
14910cb2424SMark Murray
15010cb2424SMark Murray for (i = 0; ; i++) {
15110cb2424SMark Murray if (stopseeding)
15210cb2424SMark Murray break;
15310cb2424SMark Murray if (i % 1000 == 0)
15410cb2424SMark Murray printf("Harvest: %d\n", i);
15510cb2424SMark Murray r = random()%10;
15610cb2424SMark Murray e.he_somecounter = i;
15710cb2424SMark Murray *((uint64_t *)e.he_entropy) = random();
15810cb2424SMark Murray e.he_size = 8;
15910cb2424SMark Murray e.he_destination = i;
16010cb2424SMark Murray e.he_source = (i + 3)%7;
16110cb2424SMark Murray e.he_next = NULL;
1623aa77530SMark Murray random_alg_context.ra_event_processor(&e);
16310cb2424SMark Murray usleep(r);
16410cb2424SMark Murray }
16510cb2424SMark Murray
16610cb2424SMark Murray printf("Thread #0 ends\n");
16710cb2424SMark Murray
16810cb2424SMark Murray thrd_exit(0);
16910cb2424SMark Murray
17010cb2424SMark Murray return (0);
17110cb2424SMark Murray }
17210cb2424SMark Murray
17310cb2424SMark Murray static int
ReadCSPRNG(void * threadid)17410cb2424SMark Murray ReadCSPRNG(void *threadid)
17510cb2424SMark Murray {
176d1b06863SMark Murray size_t tid, zsize;
1773aa77530SMark Murray u_int buffersize;
178d1b06863SMark Murray uint8_t *buf, *zbuf;
17910cb2424SMark Murray int i;
180d1b06863SMark Murray #ifdef DEBUG
181d1b06863SMark Murray int j;
182d1b06863SMark Murray #endif
18310cb2424SMark Murray
18410cb2424SMark Murray tid = (size_t)threadid;
18510cb2424SMark Murray printf("Thread #%zd starts\n", tid);
18610cb2424SMark Murray
1873aa77530SMark Murray while (!random_alg_context.ra_seeded())
18810cb2424SMark Murray {
1893aa77530SMark Murray random_alg_context.ra_pre_read();
19010cb2424SMark Murray usleep(100);
19110cb2424SMark Murray }
19210cb2424SMark Murray
19310cb2424SMark Murray for (i = 0; i < 100000; i++) {
1943aa77530SMark Murray buffersize = i + RANDOM_BLOCKSIZE;
1953aa77530SMark Murray buffersize -= buffersize%RANDOM_BLOCKSIZE;
1963aa77530SMark Murray buf = malloc(buffersize);
197d1b06863SMark Murray zbuf = malloc(2*i + 1024);
19810cb2424SMark Murray if (i % 1000 == 0)
199d1b06863SMark Murray printf("Thread read %zd - %d\n", tid, i);
200d1b06863SMark Murray if (buf != NULL && zbuf != NULL) {
2013aa77530SMark Murray random_alg_context.ra_pre_read();
2023aa77530SMark Murray random_alg_context.ra_read(buf, buffersize);
203d1b06863SMark Murray zsize = block_deflate(buf, zbuf, i);
204d1b06863SMark Murray if (zsize < i)
205d1b06863SMark Murray printf("ERROR!! Compressible RNG output!\n");
206d1b06863SMark Murray #ifdef DEBUG
207d1b06863SMark Murray printf("RNG output:\n");
20810cb2424SMark Murray for (j = 0; j < i; j++) {
20910cb2424SMark Murray printf(" %02X", buf[j]);
21010cb2424SMark Murray if (j % 32 == 31 || j == i - 1)
21110cb2424SMark Murray printf("\n");
21210cb2424SMark Murray }
213d1b06863SMark Murray printf("Compressed output:\n");
214d1b06863SMark Murray for (j = 0; j < zsize; j++) {
215d1b06863SMark Murray printf(" %02X", zbuf[j]);
216d1b06863SMark Murray if (j % 32 == 31 || j == zsize - 1)
217d1b06863SMark Murray printf("\n");
21810cb2424SMark Murray }
21910cb2424SMark Murray #endif
220d1b06863SMark Murray free(zbuf);
22110cb2424SMark Murray free(buf);
22210cb2424SMark Murray }
22310cb2424SMark Murray usleep(100);
22410cb2424SMark Murray }
22510cb2424SMark Murray
22610cb2424SMark Murray printf("Thread #%zd ends\n", tid);
22710cb2424SMark Murray
22810cb2424SMark Murray thrd_exit(0);
22910cb2424SMark Murray
23010cb2424SMark Murray return (0);
23110cb2424SMark Murray }
23210cb2424SMark Murray
23310cb2424SMark Murray int
main(int argc,char * argv[])23410cb2424SMark Murray main(int argc, char *argv[])
23510cb2424SMark Murray {
23610cb2424SMark Murray thrd_t threads[NUM_THREADS];
23710cb2424SMark Murray int rc;
23810cb2424SMark Murray long t;
23910cb2424SMark Murray
2403aa77530SMark Murray random_alg_context.ra_init_alg(NULL);
24110cb2424SMark Murray
24210cb2424SMark Murray for (t = 0; t < NUM_THREADS; t++) {
24310cb2424SMark Murray printf("In main: creating thread %ld\n", t);
244646041a8SMark Murray rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : ReadCSPRNG), NULL);
24510cb2424SMark Murray if (rc != thrd_success) {
24610cb2424SMark Murray printf("ERROR; return code from thrd_create() is %d\n", rc);
24710cb2424SMark Murray exit(-1);
24810cb2424SMark Murray }
24910cb2424SMark Murray }
25010cb2424SMark Murray
25110cb2424SMark Murray for (t = 2; t < NUM_THREADS; t++)
25210cb2424SMark Murray thrd_join(threads[t], &rc);
25310cb2424SMark Murray
25410cb2424SMark Murray stopseeding = 1;
25510cb2424SMark Murray
25610cb2424SMark Murray thrd_join(threads[1], &rc);
25710cb2424SMark Murray thrd_join(threads[0], &rc);
25810cb2424SMark Murray
2593aa77530SMark Murray random_alg_context.ra_deinit_alg(NULL);
26010cb2424SMark Murray
26110cb2424SMark Murray /* Last thing that main() should do */
26210cb2424SMark Murray thrd_exit(0);
26310cb2424SMark Murray
26410cb2424SMark Murray return (0);
26510cb2424SMark Murray }
266