1 /*- 2 * Copyright (c) 2013-2015 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 */ 27 28 /* 29 * This implementation of Fortuna is based on the descriptions found in 30 * ISBN 978-0-470-47424-2 "Cryptography Engineering" by Ferguson, Schneier 31 * and Kohno ("FS&K"). 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/limits.h> 38 39 #ifdef _KERNEL 40 #include <sys/param.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/malloc.h> 44 #include <sys/mutex.h> 45 #include <sys/random.h> 46 #include <sys/sysctl.h> 47 #include <sys/systm.h> 48 49 #include <machine/cpu.h> 50 51 #include <crypto/rijndael/rijndael-api-fst.h> 52 #include <crypto/sha2/sha2.h> 53 54 #include <dev/random/hash.h> 55 #include <dev/random/randomdev.h> 56 #include <dev/random/random_harvestq.h> 57 #include <dev/random/uint128.h> 58 #include <dev/random/fortuna.h> 59 #else /* !_KERNEL */ 60 #include <inttypes.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <threads.h> 65 66 #include "unit_test.h" 67 68 #include <crypto/rijndael/rijndael-api-fst.h> 69 #include <crypto/sha2/sha2.h> 70 71 #include <dev/random/hash.h> 72 #include <dev/random/randomdev.h> 73 #include <dev/random/uint128.h> 74 #include <dev/random/fortuna.h> 75 #endif /* _KERNEL */ 76 77 /* Defined in FS&K */ 78 #define RANDOM_FORTUNA_NPOOLS 32 /* The number of accumulation pools */ 79 #define RANDOM_FORTUNA_DEFPOOLSIZE 64 /* The default pool size/length for a (re)seed */ 80 #define RANDOM_FORTUNA_MAX_READ (1 << 20) /* Max bytes in a single read */ 81 82 /* 83 * The allowable range of RANDOM_FORTUNA_DEFPOOLSIZE. The default value is above. 84 * Making RANDOM_FORTUNA_DEFPOOLSIZE too large will mean a long time between reseeds, 85 * and too small may compromise initial security but get faster reseeds. 86 */ 87 #define RANDOM_FORTUNA_MINPOOLSIZE 16 88 #define RANDOM_FORTUNA_MAXPOOLSIZE UINT_MAX 89 CTASSERT(RANDOM_FORTUNA_MINPOOLSIZE <= RANDOM_FORTUNA_DEFPOOLSIZE); 90 CTASSERT(RANDOM_FORTUNA_DEFPOOLSIZE <= RANDOM_FORTUNA_MAXPOOLSIZE); 91 92 /* This algorithm (and code) presumes that RANDOM_KEYSIZE is twice as large as RANDOM_BLOCKSIZE */ 93 CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t)); 94 CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE); 95 96 /* 97 * This is the beastie that needs protecting. It contains all of the 98 * state that we are excited about. Exactly one is instantiated. 99 */ 100 static struct fortuna_state { 101 struct fs_pool { /* P_i */ 102 u_int fsp_length; /* Only the first one is used by Fortuna */ 103 struct randomdev_hash fsp_hash; 104 } fs_pool[RANDOM_FORTUNA_NPOOLS]; 105 u_int fs_reseedcount; /* ReseedCnt */ 106 uint128_t fs_counter; /* C */ 107 struct randomdev_key fs_key; /* K */ 108 u_int fs_minpoolsize; /* Extras */ 109 /* Extras for the OS */ 110 #ifdef _KERNEL 111 /* For use when 'pacing' the reseeds */ 112 sbintime_t fs_lasttime; 113 #endif 114 /* Reseed lock */ 115 mtx_t fs_mtx; 116 } fortuna_state; 117 118 #ifdef _KERNEL 119 static struct sysctl_ctx_list random_clist; 120 RANDOM_CHECK_UINT(fs_minpoolsize, RANDOM_FORTUNA_MINPOOLSIZE, RANDOM_FORTUNA_MAXPOOLSIZE); 121 #else 122 static uint8_t zero_region[RANDOM_ZERO_BLOCKSIZE]; 123 #endif 124 125 static void random_fortuna_pre_read(void); 126 static void random_fortuna_read(uint8_t *, u_int); 127 static void random_fortuna_write(uint8_t *, u_int); 128 static void random_fortuna_reseed(void); 129 static int random_fortuna_seeded(void); 130 static void random_fortuna_process_event(struct harvest_event *); 131 static void random_fortuna_init_alg(void *); 132 static void random_fortuna_deinit_alg(void *); 133 134 static void random_fortuna_reseed_internal(uint32_t *entropy_data, u_int blockcount); 135 136 struct random_algorithm random_alg_context = { 137 .ra_ident = "Fortuna", 138 .ra_init_alg = random_fortuna_init_alg, 139 .ra_deinit_alg = random_fortuna_deinit_alg, 140 .ra_pre_read = random_fortuna_pre_read, 141 .ra_read = random_fortuna_read, 142 .ra_write = random_fortuna_write, 143 .ra_reseed = random_fortuna_reseed, 144 .ra_seeded = random_fortuna_seeded, 145 .ra_event_processor = random_fortuna_process_event, 146 .ra_poolcount = RANDOM_FORTUNA_NPOOLS, 147 }; 148 149 /* ARGSUSED */ 150 static void 151 random_fortuna_init_alg(void *unused __unused) 152 { 153 int i; 154 #ifdef _KERNEL 155 struct sysctl_oid *random_fortuna_o; 156 #endif 157 158 RANDOM_RESEED_INIT_LOCK(); 159 /* 160 * Fortuna parameters. Do not adjust these unless you have 161 * have a very good clue about what they do! 162 */ 163 fortuna_state.fs_minpoolsize = RANDOM_FORTUNA_DEFPOOLSIZE; 164 #ifdef _KERNEL 165 fortuna_state.fs_lasttime = 0; 166 random_fortuna_o = SYSCTL_ADD_NODE(&random_clist, 167 SYSCTL_STATIC_CHILDREN(_kern_random), 168 OID_AUTO, "fortuna", CTLFLAG_RW, 0, 169 "Fortuna Parameters"); 170 SYSCTL_ADD_PROC(&random_clist, 171 SYSCTL_CHILDREN(random_fortuna_o), OID_AUTO, 172 "minpoolsize", CTLTYPE_UINT | CTLFLAG_RWTUN, 173 &fortuna_state.fs_minpoolsize, RANDOM_FORTUNA_DEFPOOLSIZE, 174 random_check_uint_fs_minpoolsize, "IU", 175 "Minimum pool size necessary to cause a reseed"); 176 KASSERT(fortuna_state.fs_minpoolsize > 0, ("random: Fortuna threshold must be > 0 at startup")); 177 #endif 178 179 /*- 180 * FS&K - InitializePRNG() 181 * - P_i = \epsilon 182 * - ReseedCNT = 0 183 */ 184 for (i = 0; i < RANDOM_FORTUNA_NPOOLS; i++) { 185 randomdev_hash_init(&fortuna_state.fs_pool[i].fsp_hash); 186 fortuna_state.fs_pool[i].fsp_length = 0; 187 } 188 fortuna_state.fs_reseedcount = 0; 189 /*- 190 * FS&K - InitializeGenerator() 191 * - C = 0 192 * - K = 0 193 */ 194 fortuna_state.fs_counter = UINT128_ZERO; 195 explicit_bzero(&fortuna_state.fs_key, sizeof(fortuna_state.fs_key)); 196 } 197 198 /* ARGSUSED */ 199 static void 200 random_fortuna_deinit_alg(void *unused __unused) 201 { 202 203 RANDOM_RESEED_DEINIT_LOCK(); 204 explicit_bzero(&fortuna_state, sizeof(fortuna_state)); 205 #ifdef _KERNEL 206 sysctl_ctx_free(&random_clist); 207 #endif 208 } 209 210 /*- 211 * FS&K - AddRandomEvent() 212 * Process a single stochastic event off the harvest queue 213 */ 214 static void 215 random_fortuna_process_event(struct harvest_event *event) 216 { 217 u_int pl; 218 219 RANDOM_RESEED_LOCK(); 220 /*- 221 * FS&K - P_i = P_i|<harvested stuff> 222 * Accumulate the event into the appropriate pool 223 * where each event carries the destination information. 224 * 225 * The hash_init() and hash_finish() calls are done in 226 * random_fortuna_pre_read(). 227 * 228 * We must be locked against pool state modification which can happen 229 * during accumulation/reseeding and reading/regating. 230 */ 231 pl = event->he_destination % RANDOM_FORTUNA_NPOOLS; 232 randomdev_hash_iterate(&fortuna_state.fs_pool[pl].fsp_hash, event, sizeof(*event)); 233 /*- 234 * Don't wrap the length. Doing the the hard way so as not to wrap at MAXUINT. 235 * This is a "saturating" add. 236 * XXX: FIX!!: We don't actually need lengths for anything but fs_pool[0], 237 * but it's been useful debugging to see them all. 238 */ 239 if (RANDOM_FORTUNA_MAXPOOLSIZE - fortuna_state.fs_pool[pl].fsp_length > event->he_size) 240 fortuna_state.fs_pool[pl].fsp_length += event->he_size; 241 else 242 fortuna_state.fs_pool[pl].fsp_length = RANDOM_FORTUNA_MAXPOOLSIZE; 243 explicit_bzero(event, sizeof(*event)); 244 RANDOM_RESEED_UNLOCK(); 245 } 246 247 /*- 248 * FS&K - Reseed() 249 * This introduces new key material into the output generator. 250 * Additionaly it increments the output generator's counter 251 * variable C. When C > 0, the output generator is seeded and 252 * will deliver output. 253 * The entropy_data buffer passed is a very specific size; the 254 * product of RANDOM_FORTUNA_NPOOLS and RANDOM_KEYSIZE. 255 */ 256 static void 257 random_fortuna_reseed_internal(uint32_t *entropy_data, u_int blockcount) 258 { 259 struct randomdev_hash context; 260 uint8_t hash[RANDOM_KEYSIZE]; 261 262 RANDOM_RESEED_ASSERT_LOCK_OWNED(); 263 /*- 264 * FS&K - K = Hd(K|s) where Hd(m) is H(H(0^512|m)) 265 * - C = C + 1 266 */ 267 randomdev_hash_init(&context); 268 randomdev_hash_iterate(&context, zero_region, RANDOM_ZERO_BLOCKSIZE); 269 randomdev_hash_iterate(&context, &fortuna_state.fs_key, sizeof(fortuna_state.fs_key)); 270 randomdev_hash_iterate(&context, entropy_data, RANDOM_KEYSIZE*blockcount); 271 randomdev_hash_finish(&context, hash); 272 randomdev_hash_init(&context); 273 randomdev_hash_iterate(&context, hash, RANDOM_KEYSIZE); 274 randomdev_hash_finish(&context, hash); 275 randomdev_encrypt_init(&fortuna_state.fs_key, hash); 276 explicit_bzero(hash, sizeof(hash)); 277 /* Unblock the device if this is the first time we are reseeding. */ 278 if (uint128_is_zero(fortuna_state.fs_counter)) 279 randomdev_unblock(); 280 uint128_increment(&fortuna_state.fs_counter); 281 } 282 283 /*- 284 * FS&K - GenerateBlocks() 285 * Generate a number of complete blocks of random output. 286 */ 287 static __inline void 288 random_fortuna_genblocks(uint8_t *buf, u_int blockcount) 289 { 290 u_int i; 291 292 RANDOM_RESEED_ASSERT_LOCK_OWNED(); 293 for (i = 0; i < blockcount; i++) { 294 /*- 295 * FS&K - r = r|E(K,C) 296 * - C = C + 1 297 */ 298 randomdev_encrypt(&fortuna_state.fs_key, &fortuna_state.fs_counter, buf, RANDOM_BLOCKSIZE); 299 buf += RANDOM_BLOCKSIZE; 300 uint128_increment(&fortuna_state.fs_counter); 301 } 302 } 303 304 /*- 305 * FS&K - PseudoRandomData() 306 * This generates no more than 2^20 bytes of data, and cleans up its 307 * internal state when finished. It is assumed that a whole number of 308 * blocks are available for writing; any excess generated will be 309 * ignored. 310 */ 311 static __inline void 312 random_fortuna_genrandom(uint8_t *buf, u_int bytecount) 313 { 314 static uint8_t temp[RANDOM_BLOCKSIZE*(RANDOM_KEYS_PER_BLOCK)]; 315 u_int blockcount; 316 317 RANDOM_RESEED_ASSERT_LOCK_OWNED(); 318 /*- 319 * FS&K - assert(n < 2^20 (== 1 MB) 320 * - r = first-n-bytes(GenerateBlocks(ceil(n/16))) 321 * - K = GenerateBlocks(2) 322 */ 323 KASSERT((bytecount <= RANDOM_FORTUNA_MAX_READ), ("invalid single read request to Fortuna of %d bytes", bytecount)); 324 blockcount = (bytecount + RANDOM_BLOCKSIZE - 1)/RANDOM_BLOCKSIZE; 325 random_fortuna_genblocks(buf, blockcount); 326 random_fortuna_genblocks(temp, RANDOM_KEYS_PER_BLOCK); 327 randomdev_encrypt_init(&fortuna_state.fs_key, temp); 328 explicit_bzero(temp, sizeof(temp)); 329 } 330 331 /*- 332 * FS&K - RandomData() (Part 1) 333 * Used to return processed entropy from the PRNG. There is a pre_read 334 * required to be present (but it can be a stub) in order to allow 335 * specific actions at the begin of the read. 336 */ 337 void 338 random_fortuna_pre_read(void) 339 { 340 #ifdef _KERNEL 341 sbintime_t now; 342 #endif 343 struct randomdev_hash context; 344 uint32_t s[RANDOM_FORTUNA_NPOOLS*RANDOM_KEYSIZE_WORDS]; 345 uint8_t temp[RANDOM_KEYSIZE]; 346 u_int i; 347 348 KASSERT(fortuna_state.fs_minpoolsize > 0, ("random: Fortuna threshold must be > 0")); 349 #ifdef _KERNEL 350 /* FS&K - Use 'getsbinuptime()' to prevent reseed-spamming. */ 351 now = getsbinuptime(); 352 #endif 353 RANDOM_RESEED_LOCK(); 354 355 if (fortuna_state.fs_pool[0].fsp_length >= fortuna_state.fs_minpoolsize 356 #ifdef _KERNEL 357 /* FS&K - Use 'getsbinuptime()' to prevent reseed-spamming. */ 358 && (now - fortuna_state.fs_lasttime > hz/10) 359 #endif 360 ) { 361 #ifdef _KERNEL 362 fortuna_state.fs_lasttime = now; 363 #endif 364 365 /* FS&K - ReseedCNT = ReseedCNT + 1 */ 366 fortuna_state.fs_reseedcount++; 367 /* s = \epsilon at start */ 368 for (i = 0; i < RANDOM_FORTUNA_NPOOLS; i++) { 369 /* FS&K - if Divides(ReseedCnt, 2^i) ... */ 370 if ((fortuna_state.fs_reseedcount % (1 << i)) == 0) { 371 /*- 372 * FS&K - temp = (P_i) 373 * - P_i = \epsilon 374 * - s = s|H(temp) 375 */ 376 randomdev_hash_finish(&fortuna_state.fs_pool[i].fsp_hash, temp); 377 randomdev_hash_init(&fortuna_state.fs_pool[i].fsp_hash); 378 fortuna_state.fs_pool[i].fsp_length = 0; 379 randomdev_hash_init(&context); 380 randomdev_hash_iterate(&context, temp, RANDOM_KEYSIZE); 381 randomdev_hash_finish(&context, s + i*RANDOM_KEYSIZE_WORDS); 382 } else 383 break; 384 } 385 #ifdef RANDOM_DEBUG 386 { 387 u_int j; 388 389 printf("random: reseedcount [%d]", fortuna_state.fs_reseedcount); 390 for (j = 0; j < RANDOM_FORTUNA_NPOOLS; j++) 391 printf(" %X", fortuna_state.fs_pool[j].fsp_length); 392 printf("\n"); 393 } 394 #endif 395 /* FS&K */ 396 random_fortuna_reseed_internal(s, i < RANDOM_FORTUNA_NPOOLS ? i + 1 : RANDOM_FORTUNA_NPOOLS); 397 /* Clean up and secure */ 398 explicit_bzero(s, sizeof(s)); 399 explicit_bzero(temp, sizeof(temp)); 400 explicit_bzero(&context, sizeof(context)); 401 } 402 RANDOM_RESEED_UNLOCK(); 403 } 404 405 /*- 406 * FS&K - RandomData() (Part 2) 407 * Main read from Fortuna, continued. May be called multiple times after 408 * the random_fortuna_pre_read() above. 409 * The supplied buf MUST be a multiple of RANDOM_BLOCKSIZE in size. 410 * Lots of code presumes this for efficiency, both here and in other 411 * routines. You are NOT allowed to break this! 412 */ 413 void 414 random_fortuna_read(uint8_t *buf, u_int bytecount) 415 { 416 417 KASSERT((bytecount % RANDOM_BLOCKSIZE) == 0, ("%s(): bytecount (= %d) must be a multiple of %d", __func__, bytecount, RANDOM_BLOCKSIZE )); 418 RANDOM_RESEED_LOCK(); 419 random_fortuna_genrandom(buf, bytecount); 420 RANDOM_RESEED_UNLOCK(); 421 } 422 423 /* Internal function to hand external entropy to the PRNG. */ 424 void 425 random_fortuna_write(uint8_t *buf, u_int count) 426 { 427 static u_int destination = 0; 428 struct harvest_event event; 429 struct randomdev_hash hash; 430 uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp; 431 int i; 432 433 /* Extra timing here is helpful to scrape scheduler timing entropy */ 434 randomdev_hash_init(&hash); 435 timestamp = (uint32_t)get_cyclecount(); 436 randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp)); 437 randomdev_hash_iterate(&hash, buf, count); 438 timestamp = (uint32_t)get_cyclecount(); 439 randomdev_hash_iterate(&hash, ×tamp, sizeof(timestamp)); 440 randomdev_hash_finish(&hash, entropy_data); 441 explicit_bzero(&hash, sizeof(hash)); 442 for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) { 443 event.he_somecounter = (uint32_t)get_cyclecount(); 444 event.he_size = sizeof(event.he_entropy); 445 event.he_bits = event.he_size/8; 446 event.he_source = RANDOM_CACHED; 447 event.he_destination = destination++; /* Harmless cheating */ 448 memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy)); 449 random_fortuna_process_event(&event); 450 } 451 explicit_bzero(entropy_data, sizeof(entropy_data)); 452 } 453 454 void 455 random_fortuna_reseed(void) 456 { 457 } 458 459 int 460 random_fortuna_seeded(void) 461 { 462 463 return (!uint128_is_zero(fortuna_state.fs_counter)); 464 } 465