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