1273872Smarkm/*- 2284959Smarkm * Copyright (c) 2000-2015 Mark R V Murray 3273872Smarkm * All rights reserved. 4273872Smarkm * 5273872Smarkm * Redistribution and use in source and binary forms, with or without 6273872Smarkm * modification, are permitted provided that the following conditions 7273872Smarkm * are met: 8273872Smarkm * 1. Redistributions of source code must retain the above copyright 9273872Smarkm * notice, this list of conditions and the following disclaimer 10273872Smarkm * in this position and unchanged. 11273872Smarkm * 2. Redistributions in binary form must reproduce the above copyright 12273872Smarkm * notice, this list of conditions and the following disclaimer in the 13273872Smarkm * documentation and/or other materials provided with the distribution. 14273872Smarkm * 15273872Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16273872Smarkm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17273872Smarkm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18273872Smarkm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19273872Smarkm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20273872Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21273872Smarkm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22273872Smarkm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23273872Smarkm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24273872Smarkm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25273872Smarkm * 26273872Smarkm * $FreeBSD$ 27273872Smarkm */ 28273872Smarkm 29273872Smarkm/* 30273872Smarkm Build this by going: 31273872Smarkm 32287023Smarkmcc -g -O0 -pthread -DRANDOM_<alg> -I../.. -lstdthreads -Wall \ 33273872Smarkm unit_test.c \ 34273872Smarkm yarrow.c \ 35273872Smarkm fortuna.c \ 36273872Smarkm hash.c \ 37273872Smarkm ../../crypto/rijndael/rijndael-api-fst.c \ 38273872Smarkm ../../crypto/rijndael/rijndael-alg-fst.c \ 39292782Sallanjude ../../crypto/sha2/sha256c.c \ 40284959Smarkm -lz \ 41273872Smarkm -o unit_test 42273872Smarkm./unit_test 43273872Smarkm 44273872SmarkmWhere <alg> is YARROW or FORTUNA. 45273872Smarkm*/ 46273872Smarkm 47273872Smarkm#include <sys/types.h> 48273872Smarkm#include <inttypes.h> 49286839Smarkm#include <stdbool.h> 50273872Smarkm#include <stdio.h> 51273872Smarkm#include <stdlib.h> 52273872Smarkm#include <threads.h> 53273872Smarkm#include <unistd.h> 54284959Smarkm#include <zlib.h> 55273872Smarkm 56285422Smarkm#include "randomdev.h" 57273872Smarkm#include "unit_test.h" 58273872Smarkm 59284959Smarkm#define NUM_THREADS 3 60284959Smarkm#define DEBUG 61273872Smarkm 62273872Smarkmstatic volatile int stopseeding = 0; 63273872Smarkm 64284959Smarkmstatic __inline void 65284959Smarkmcheck_err(int err, const char *func) 66284959Smarkm{ 67284959Smarkm if (err != Z_OK) { 68284959Smarkm fprintf(stderr, "Compress error in %s: %d\n", func, err); 69284959Smarkm exit(0); 70284959Smarkm } 71284959Smarkm} 72284959Smarkm 73284959Smarkmvoid * 74284959Smarkmmyalloc(void *q, unsigned n, unsigned m) 75284959Smarkm{ 76284959Smarkm q = Z_NULL; 77284959Smarkm return (calloc(n, m)); 78284959Smarkm} 79284959Smarkm 80284959Smarkmvoid myfree(void *q, void *p) 81284959Smarkm{ 82284959Smarkm q = Z_NULL; 83284959Smarkm free(p); 84284959Smarkm} 85284959Smarkm 86284959Smarkmsize_t 87284959Smarkmblock_deflate(uint8_t *uncompr, uint8_t *compr, const size_t len) 88284959Smarkm{ 89284959Smarkm z_stream c_stream; 90284959Smarkm int err; 91284959Smarkm 92284959Smarkm if (len == 0) 93284959Smarkm return (0); 94284959Smarkm 95284959Smarkm c_stream.zalloc = myalloc; 96284959Smarkm c_stream.zfree = myfree; 97284959Smarkm c_stream.opaque = NULL; 98284959Smarkm 99284959Smarkm err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); 100284959Smarkm check_err(err, "deflateInit"); 101284959Smarkm 102284959Smarkm c_stream.next_in = uncompr; 103284959Smarkm c_stream.next_out = compr; 104284959Smarkm c_stream.avail_in = len; 105284959Smarkm c_stream.avail_out = len*2u +512u; 106284959Smarkm 107284959Smarkm while (c_stream.total_in != len && c_stream.total_out < (len*2u + 512u)) { 108284959Smarkm err = deflate(&c_stream, Z_NO_FLUSH); 109284959Smarkm#ifdef DEBUG 110285422Smarkm printf("deflate progress: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out); 111284959Smarkm#endif 112284959Smarkm check_err(err, "deflate(..., Z_NO_FLUSH)"); 113284959Smarkm } 114284959Smarkm 115284959Smarkm for (;;) { 116284959Smarkm err = deflate(&c_stream, Z_FINISH); 117284959Smarkm#ifdef DEBUG 118285422Smarkm printf("deflate final: len = %zd total_in = %lu total_out = %lu\n", len, c_stream.total_in, c_stream.total_out); 119284959Smarkm#endif 120284959Smarkm if (err == Z_STREAM_END) break; 121284959Smarkm check_err(err, "deflate(..., Z_STREAM_END)"); 122284959Smarkm } 123284959Smarkm 124284959Smarkm err = deflateEnd(&c_stream); 125284959Smarkm check_err(err, "deflateEnd"); 126284959Smarkm 127284959Smarkm return ((size_t)c_stream.total_out); 128284959Smarkm} 129284959Smarkm 130273872Smarkmvoid 131285422Smarkmrandomdev_unblock(void) 132273872Smarkm{ 133273872Smarkm 134273872Smarkm#if 0 135273872Smarkm if (mtx_trylock(&random_reseed_mtx) == thrd_busy) 136273872Smarkm printf("Mutex held. Good.\n"); 137273872Smarkm else { 138273872Smarkm printf("Mutex not held. PANIC!!\n"); 139273872Smarkm thrd_exit(0); 140273872Smarkm } 141273872Smarkm#endif 142273872Smarkm printf("random: unblocking device.\n"); 143273872Smarkm} 144273872Smarkm 145273872Smarkmstatic int 146273872SmarkmRunHarvester(void *arg __unused) 147273872Smarkm{ 148273872Smarkm int i, r; 149273872Smarkm struct harvest_event e; 150273872Smarkm 151273872Smarkm for (i = 0; ; i++) { 152273872Smarkm if (stopseeding) 153273872Smarkm break; 154273872Smarkm if (i % 1000 == 0) 155273872Smarkm printf("Harvest: %d\n", i); 156273872Smarkm r = random()%10; 157273872Smarkm e.he_somecounter = i; 158273872Smarkm *((uint64_t *)e.he_entropy) = random(); 159273872Smarkm e.he_size = 8; 160273872Smarkm e.he_bits = random()%4; 161273872Smarkm e.he_destination = i; 162273872Smarkm e.he_source = (i + 3)%7; 163273872Smarkm e.he_next = NULL; 164285422Smarkm random_alg_context.ra_event_processor(&e); 165273872Smarkm usleep(r); 166273872Smarkm } 167273872Smarkm 168273872Smarkm printf("Thread #0 ends\n"); 169273872Smarkm 170273872Smarkm thrd_exit(0); 171273872Smarkm 172273872Smarkm return (0); 173273872Smarkm} 174273872Smarkm 175273872Smarkmstatic int 176273872SmarkmReadCSPRNG(void *threadid) 177273872Smarkm{ 178284959Smarkm size_t tid, zsize; 179285422Smarkm u_int buffersize; 180284959Smarkm uint8_t *buf, *zbuf; 181273872Smarkm int i; 182284959Smarkm#ifdef DEBUG 183284959Smarkm int j; 184284959Smarkm#endif 185273872Smarkm 186273872Smarkm tid = (size_t)threadid; 187273872Smarkm printf("Thread #%zd starts\n", tid); 188273872Smarkm 189285422Smarkm while (!random_alg_context.ra_seeded()) 190273872Smarkm { 191285422Smarkm random_alg_context.ra_pre_read(); 192273872Smarkm usleep(100); 193273872Smarkm } 194273872Smarkm 195273872Smarkm for (i = 0; i < 100000; i++) { 196285422Smarkm buffersize = i + RANDOM_BLOCKSIZE; 197285422Smarkm buffersize -= buffersize%RANDOM_BLOCKSIZE; 198285422Smarkm buf = malloc(buffersize); 199284959Smarkm zbuf = malloc(2*i + 1024); 200273872Smarkm if (i % 1000 == 0) 201284959Smarkm printf("Thread read %zd - %d\n", tid, i); 202284959Smarkm if (buf != NULL && zbuf != NULL) { 203285422Smarkm random_alg_context.ra_pre_read(); 204285422Smarkm random_alg_context.ra_read(buf, buffersize); 205284959Smarkm zsize = block_deflate(buf, zbuf, i); 206284959Smarkm if (zsize < i) 207284959Smarkm printf("ERROR!! Compressible RNG output!\n"); 208284959Smarkm#ifdef DEBUG 209284959Smarkm printf("RNG output:\n"); 210273872Smarkm for (j = 0; j < i; j++) { 211273872Smarkm printf(" %02X", buf[j]); 212273872Smarkm if (j % 32 == 31 || j == i - 1) 213273872Smarkm printf("\n"); 214273872Smarkm } 215284959Smarkm printf("Compressed output:\n"); 216284959Smarkm for (j = 0; j < zsize; j++) { 217284959Smarkm printf(" %02X", zbuf[j]); 218284959Smarkm if (j % 32 == 31 || j == zsize - 1) 219284959Smarkm printf("\n"); 220273872Smarkm } 221273872Smarkm#endif 222284959Smarkm free(zbuf); 223273872Smarkm free(buf); 224273872Smarkm } 225273872Smarkm usleep(100); 226273872Smarkm } 227273872Smarkm 228273872Smarkm printf("Thread #%zd ends\n", tid); 229273872Smarkm 230273872Smarkm thrd_exit(0); 231273872Smarkm 232273872Smarkm return (0); 233273872Smarkm} 234273872Smarkm 235273872Smarkmint 236273872Smarkmmain(int argc, char *argv[]) 237273872Smarkm{ 238273872Smarkm thrd_t threads[NUM_THREADS]; 239273872Smarkm int rc; 240273872Smarkm long t; 241273872Smarkm 242285422Smarkm random_alg_context.ra_init_alg(NULL); 243273872Smarkm 244273872Smarkm for (t = 0; t < NUM_THREADS; t++) { 245273872Smarkm printf("In main: creating thread %ld\n", t); 246286839Smarkm rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : ReadCSPRNG), NULL); 247273872Smarkm if (rc != thrd_success) { 248273872Smarkm printf("ERROR; return code from thrd_create() is %d\n", rc); 249273872Smarkm exit(-1); 250273872Smarkm } 251273872Smarkm } 252273872Smarkm 253273872Smarkm for (t = 2; t < NUM_THREADS; t++) 254273872Smarkm thrd_join(threads[t], &rc); 255273872Smarkm 256273872Smarkm stopseeding = 1; 257273872Smarkm 258273872Smarkm thrd_join(threads[1], &rc); 259273872Smarkm thrd_join(threads[0], &rc); 260273872Smarkm 261285422Smarkm random_alg_context.ra_deinit_alg(NULL); 262273872Smarkm 263273872Smarkm /* Last thing that main() should do */ 264273872Smarkm thrd_exit(0); 265273872Smarkm 266273872Smarkm return (0); 267273872Smarkm} 268