1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Software based random number provider for the Kernel Cryptographic 30 * Framework (KCF). This provider periodically collects unpredictable input 31 * from external sources and processes it into a pool of entropy (randomness) 32 * in order to satisfy requests for random bits from kCF. It implements 33 * software-based mixing, extraction, and generation algorithms. 34 * 35 * A history note: The software-based algorithms in this file used to be 36 * part of the /dev/random driver. 37 */ 38 39 #include <sys/types.h> 40 #include <sys/errno.h> 41 #include <sys/debug.h> 42 #include <vm/seg_kmem.h> 43 #include <vm/hat.h> 44 #include <sys/systm.h> 45 #include <sys/memlist.h> 46 #include <sys/cmn_err.h> 47 #include <sys/ksynch.h> 48 #include <sys/random.h> 49 #include <sys/ddi.h> 50 #include <sys/mman.h> 51 #include <sys/sysmacros.h> 52 #include <sys/mem_config.h> 53 #include <sys/time.h> 54 #include <sys/crypto/spi.h> 55 #include <sys/sha1.h> 56 #include <sys/sunddi.h> 57 #include <sys/modctl.h> 58 59 #define RNDPOOLSIZE 1024 /* Pool size in bytes */ 60 #define HASHBUFSIZE 64 /* Buffer size used for pool mixing */ 61 #define MAXMEMBLOCKS 16384 /* Number of memory blocks to scan */ 62 #define MEMBLOCKSIZE 4096 /* Size of memory block to read */ 63 #define MINEXTRACTBITS 160 /* Min entropy level for extraction */ 64 #define TIMEOUT_INTERVAL 5 /* Periodic mixing interval in secs */ 65 66 /* Hash-algo generic definitions. For now, they are SHA1's. */ 67 #define HASHSIZE 20 68 #define HASH_CTX SHA1_CTX 69 #define HashInit(ctx) SHA1Init((ctx)) 70 #define HashUpdate(ctx, p, s) SHA1Update((ctx), (p), (s)) 71 #define HashFinal(d, ctx) SHA1Final((d), (ctx)) 72 73 /* Physical memory entropy source */ 74 typedef struct physmem_entsrc_s { 75 uint8_t *parity; /* parity bit vector */ 76 caddr_t pmbuf; /* buffer for memory block */ 77 uint32_t nblocks; /* number of memory blocks */ 78 int entperblock; /* entropy bits per block read */ 79 hrtime_t last_diff; /* previous time to process a block */ 80 hrtime_t last_delta; /* previous time delta */ 81 hrtime_t last_delta2; /* previous 2nd order time delta */ 82 } physmem_entsrc_t; 83 84 static uint32_t srndpool[RNDPOOLSIZE/4]; /* Pool of random bits */ 85 static uint32_t buffer[RNDPOOLSIZE/4]; /* entropy mixed in later */ 86 static int buffer_bytes; /* bytes written to buffer */ 87 static uint32_t entropy_bits; /* pool's current amount of entropy */ 88 static kmutex_t srndpool_lock; /* protects r/w accesses to the pool, */ 89 /* and the global variables */ 90 static kmutex_t buffer_lock; /* protects r/w accesses to buffer */ 91 static kcondvar_t srndpool_read_cv; /* serializes poll/read syscalls */ 92 static int pindex; /* Global index for adding/extracting */ 93 /* from the pool */ 94 static int bstart, bindex; /* Global vars for adding/extracting */ 95 /* from the buffer */ 96 static uint8_t leftover[HASHSIZE]; /* leftover output */ 97 static int leftover_bytes; /* leftover length */ 98 99 static physmem_entsrc_t entsrc; /* Physical mem as an entropy source */ 100 static timeout_id_t rnd_timeout_id; 101 static int snum_waiters; 102 static crypto_kcf_provider_handle_t swrand_prov_handle = NULL; 103 swrand_stats_t swrand_stats; 104 105 static int physmem_ent_init(physmem_entsrc_t *); 106 static void physmem_ent_fini(physmem_entsrc_t *); 107 static void physmem_ent_gen(physmem_entsrc_t *); 108 static int physmem_parity_update(uint8_t *, uint32_t, int); 109 static void physmem_count_blocks(); 110 static void rnd_dr_callback_post_add(void *, pgcnt_t); 111 static int rnd_dr_callback_pre_del(void *, pgcnt_t); 112 static void rnd_dr_callback_post_del(void *, pgcnt_t, int); 113 static void rnd_handler(void *arg); 114 static void swrand_init(); 115 static void swrand_schedule_timeout(void); 116 static int swrand_get_entropy(uint8_t *ptr, size_t len, boolean_t); 117 static void swrand_add_entropy(uint8_t *ptr, size_t len, uint16_t entropy_est); 118 static void swrand_add_entropy_later(uint8_t *ptr, size_t len); 119 120 /* Dynamic Reconfiguration related declarations */ 121 kphysm_setup_vector_t rnd_dr_callback_vec = { 122 KPHYSM_SETUP_VECTOR_VERSION, 123 rnd_dr_callback_post_add, 124 rnd_dr_callback_pre_del, 125 rnd_dr_callback_post_del 126 }; 127 128 extern struct mod_ops mod_cryptoops; 129 130 /* 131 * Module linkage information for the kernel. 132 */ 133 static struct modlcrypto modlcrypto = { 134 &mod_cryptoops, 135 "Kernel Random number Provider %I%" 136 }; 137 138 static struct modlinkage modlinkage = { 139 MODREV_1, 140 (void *)&modlcrypto, 141 NULL 142 }; 143 144 /* 145 * CSPI information (entry points, provider info, etc.) 146 */ 147 static void swrand_provider_status(crypto_provider_handle_t, uint_t *); 148 149 static crypto_control_ops_t swrand_control_ops = { 150 swrand_provider_status 151 }; 152 153 static int swrand_seed_random(crypto_provider_handle_t, crypto_session_id_t, 154 uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t); 155 static int swrand_generate_random(crypto_provider_handle_t, 156 crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t); 157 158 static crypto_random_number_ops_t swrand_random_number_ops = { 159 swrand_seed_random, 160 swrand_generate_random 161 }; 162 163 static crypto_ops_t swrand_crypto_ops = { 164 &swrand_control_ops, 165 NULL, 166 NULL, 167 NULL, 168 NULL, 169 NULL, 170 NULL, 171 NULL, 172 &swrand_random_number_ops, 173 NULL, 174 NULL, 175 NULL, 176 NULL, 177 NULL 178 }; 179 180 static crypto_provider_info_t swrand_prov_info = { 181 CRYPTO_SPI_VERSION_1, 182 "Kernel Random Number Provider", 183 CRYPTO_SW_PROVIDER, 184 {&modlinkage}, 185 NULL, 186 &swrand_crypto_ops, 187 0, 188 NULL 189 }; 190 191 int 192 _init(void) 193 { 194 int ret; 195 hrtime_t ts; 196 time_t now; 197 198 /* 199 * Register with KCF. If the registration fails, return error. 200 */ 201 if ((ret = crypto_register_provider(&swrand_prov_info, 202 &swrand_prov_handle)) != CRYPTO_SUCCESS) { 203 cmn_err(CE_WARN, "swrand : Kernel Random Number Provider " 204 "disabled for /dev/random use"); 205 return (EACCES); 206 } 207 208 mutex_init(&srndpool_lock, NULL, MUTEX_DEFAULT, NULL); 209 mutex_init(&buffer_lock, NULL, MUTEX_DEFAULT, NULL); 210 cv_init(&srndpool_read_cv, NULL, CV_DEFAULT, NULL); 211 entropy_bits = 0; 212 pindex = 0; 213 bindex = 0; 214 bstart = 0; 215 snum_waiters = 0; 216 leftover_bytes = 0; 217 buffer_bytes = 0; 218 219 /* 220 * Initialize the pool using 221 * . 2 unpredictable times: high resolution time since the boot-time, 222 * and the current time-of-the day. 223 * . The initial physical memory state. 224 */ 225 ts = gethrtime(); 226 swrand_add_entropy((uint8_t *)&ts, sizeof (ts), 0); 227 228 (void) drv_getparm(TIME, &now); 229 swrand_add_entropy((uint8_t *)&now, sizeof (now), 0); 230 231 ret = kphysm_setup_func_register(&rnd_dr_callback_vec, NULL); 232 ASSERT(ret == 0); 233 234 if (physmem_ent_init(&entsrc) != 0) { 235 mutex_destroy(&srndpool_lock); 236 mutex_destroy(&buffer_lock); 237 cv_destroy(&srndpool_read_cv); 238 (void) crypto_unregister_provider(swrand_prov_handle); 239 return (ENOMEM); 240 } 241 242 if ((ret = mod_install(&modlinkage)) != 0) { 243 mutex_destroy(&srndpool_lock); 244 mutex_destroy(&buffer_lock); 245 cv_destroy(&srndpool_read_cv); 246 physmem_ent_fini(&entsrc); 247 (void) crypto_unregister_provider(swrand_prov_handle); 248 return (ret); 249 } 250 251 /* Schedule periodic mixing of the pool. */ 252 mutex_enter(&srndpool_lock); 253 swrand_schedule_timeout(); 254 mutex_exit(&srndpool_lock); 255 256 return (0); 257 } 258 259 int 260 _info(struct modinfo *modinfop) 261 { 262 return (mod_info(&modlinkage, modinfop)); 263 } 264 265 /* 266 * Control entry points. 267 */ 268 /* ARGSUSED */ 269 static void 270 swrand_provider_status(crypto_provider_handle_t provider, uint_t *status) 271 { 272 *status = CRYPTO_PROVIDER_READY; 273 } 274 275 /* 276 * Random number entry points. 277 */ 278 /* ARGSUSED */ 279 static int 280 swrand_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid, 281 uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags, 282 crypto_req_handle_t req) 283 { 284 /* The entropy estimate is always 0 in this path */ 285 if (flags & CRYPTO_SEED_NOW) 286 swrand_add_entropy(buf, len, 0); 287 else 288 swrand_add_entropy_later(buf, len); 289 return (CRYPTO_SUCCESS); 290 } 291 292 /* ARGSUSED */ 293 static int 294 swrand_generate_random(crypto_provider_handle_t provider, 295 crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req) 296 { 297 if (crypto_kmflag(req) == KM_NOSLEEP) 298 (void) swrand_get_entropy(buf, len, B_TRUE); 299 else 300 (void) swrand_get_entropy(buf, len, B_FALSE); 301 302 return (CRYPTO_SUCCESS); 303 } 304 305 306 /* 307 * Extraction of entropy from the pool. 308 * 309 * Returns "len" random bytes in *ptr. 310 * Try to gather some more entropy by calling physmem_ent_gen() when less than 311 * MINEXTRACTBITS are present in the pool. 312 * Will block if not enough entropy was available and the call is blocking. 313 */ 314 static int 315 swrand_get_entropy(uint8_t *ptr, size_t len, boolean_t nonblock) 316 { 317 int i, bytes; 318 HASH_CTX hashctx; 319 uint8_t digest[HASHSIZE], *pool; 320 321 mutex_enter(&srndpool_lock); 322 if (leftover_bytes > 0) { 323 bytes = min(len, leftover_bytes); 324 bcopy(leftover, ptr, bytes); 325 len -= bytes; 326 ptr += bytes; 327 leftover_bytes -= bytes; 328 if (leftover_bytes > 0) 329 ovbcopy(leftover+bytes, leftover, leftover_bytes); 330 } 331 332 while (len > 0) { 333 334 /* Check if there is enough entropy */ 335 while (entropy_bits < MINEXTRACTBITS) { 336 337 physmem_ent_gen(&entsrc); 338 339 if (entropy_bits < MINEXTRACTBITS && 340 nonblock == B_TRUE) { 341 mutex_exit(&srndpool_lock); 342 return (EAGAIN); 343 } 344 345 if (entropy_bits < MINEXTRACTBITS) { 346 ASSERT(nonblock == B_FALSE); 347 snum_waiters++; 348 if (cv_wait_sig(&srndpool_read_cv, 349 &srndpool_lock) == 0) { 350 snum_waiters--; 351 mutex_exit(&srndpool_lock); 352 return (EINTR); 353 } 354 snum_waiters--; 355 } 356 } 357 358 /* Figure out how many bytes to extract */ 359 bytes = min(HASHSIZE, len); 360 bytes = min(bytes, entropy_bits/8); 361 entropy_bits -= bytes * 8; 362 BUMP_SWRAND_STATS(ss_entOut, bytes * 8); 363 swrand_stats.ss_entEst = entropy_bits; 364 365 /* Extract entropy by hashing pool content */ 366 HashInit(&hashctx); 367 HashUpdate(&hashctx, (uint8_t *)srndpool, RNDPOOLSIZE); 368 HashFinal(digest, &hashctx); 369 370 /* 371 * Feed the digest back into the pool so next 372 * extraction produces different result 373 */ 374 pool = (uint8_t *)srndpool; 375 for (i = 0; i < HASHSIZE; i++) { 376 pool[pindex++] ^= digest[i]; 377 /* pindex modulo RNDPOOLSIZE */ 378 pindex &= (RNDPOOLSIZE - 1); 379 } 380 381 /* 382 * Hash the digest again before output to obscure 383 * what was fed back to the pool. 384 */ 385 HashInit(&hashctx); 386 HashUpdate(&hashctx, digest, HASHSIZE); 387 if (len >= HASHSIZE) 388 HashFinal(ptr, &hashctx); 389 else { 390 HashFinal(digest, &hashctx); 391 bcopy(digest, ptr, bytes); 392 leftover_bytes = HASHSIZE - bytes; 393 bcopy(digest + bytes, leftover, leftover_bytes); 394 } 395 396 len -= bytes; 397 ptr += bytes; 398 BUMP_SWRAND_STATS(ss_bytesOut, bytes); 399 } 400 mutex_exit(&srndpool_lock); 401 return (0); 402 } 403 404 #define SWRAND_ADD_BYTES(ptr, len, i, pool) \ 405 ASSERT((ptr) != NULL && (len) > 0); \ 406 BUMP_SWRAND_STATS(ss_bytesIn, (len)); \ 407 while ((len)--) { \ 408 (pool)[(i)++] ^= *(ptr); \ 409 (ptr)++; \ 410 (i) &= (RNDPOOLSIZE - 1); \ 411 } 412 413 /* Write some more user-provided entropy to the pool */ 414 static void 415 swrand_add_bytes(uint8_t *ptr, size_t len) 416 { 417 uint8_t *pool = (uint8_t *)srndpool; 418 419 ASSERT(MUTEX_HELD(&srndpool_lock)); 420 SWRAND_ADD_BYTES(ptr, len, pindex, pool); 421 } 422 423 /* 424 * Add bytes to buffer. Adding the buffer to the random pool 425 * is deferred until the random pool is mixed. 426 */ 427 static void 428 swrand_add_bytes_later(uint8_t *ptr, size_t len) 429 { 430 uint8_t *pool = (uint8_t *)buffer; 431 432 ASSERT(MUTEX_HELD(&buffer_lock)); 433 SWRAND_ADD_BYTES(ptr, len, bindex, pool); 434 buffer_bytes += len; 435 } 436 437 #undef SWRAND_ADD_BYTES 438 439 /* Mix the pool */ 440 static void 441 swrand_mix_pool(uint16_t entropy_est) 442 { 443 int i, j, k, start; 444 HASH_CTX hashctx; 445 uint8_t digest[HASHSIZE]; 446 uint8_t *pool = (uint8_t *)srndpool; 447 uint8_t *bp = (uint8_t *)buffer; 448 449 ASSERT(MUTEX_HELD(&srndpool_lock)); 450 451 /* add deferred bytes */ 452 mutex_enter(&buffer_lock); 453 if (buffer_bytes > 0) { 454 if (buffer_bytes >= RNDPOOLSIZE) { 455 for (i = 0; i < RNDPOOLSIZE/4; i++) { 456 srndpool[i] ^= buffer[i]; 457 buffer[i] = 0; 458 } 459 bstart = bindex = 0; 460 } else { 461 for (i = 0; i < buffer_bytes; i++) { 462 pool[pindex++] ^= bp[bstart]; 463 bp[bstart++] = 0; 464 pindex &= (RNDPOOLSIZE - 1); 465 bstart &= (RNDPOOLSIZE - 1); 466 } 467 ASSERT(bstart == bindex); 468 } 469 buffer_bytes = 0; 470 } 471 mutex_exit(&buffer_lock); 472 473 start = 0; 474 for (i = 0; i < RNDPOOLSIZE/HASHSIZE + 1; i++) { 475 HashInit(&hashctx); 476 477 /* Hash a buffer centered on a block in the pool */ 478 if (start + HASHBUFSIZE <= RNDPOOLSIZE) 479 HashUpdate(&hashctx, &pool[start], HASHBUFSIZE); 480 else { 481 HashUpdate(&hashctx, &pool[start], 482 RNDPOOLSIZE - start); 483 HashUpdate(&hashctx, pool, 484 HASHBUFSIZE - RNDPOOLSIZE + start); 485 } 486 HashFinal(digest, &hashctx); 487 488 /* XOR the hash result back into the block */ 489 k = (start + HASHSIZE) & (RNDPOOLSIZE - 1); 490 for (j = 0; j < HASHSIZE; j++) { 491 pool[k++] ^= digest[j]; 492 k &= (RNDPOOLSIZE - 1); 493 } 494 495 /* Slide the hash buffer and repeat with next block */ 496 start = (start + HASHSIZE) & (RNDPOOLSIZE - 1); 497 } 498 499 entropy_bits += entropy_est; 500 if (entropy_bits > RNDPOOLSIZE * 8) 501 entropy_bits = RNDPOOLSIZE * 8; 502 503 swrand_stats.ss_entEst = entropy_bits; 504 BUMP_SWRAND_STATS(ss_entIn, entropy_est); 505 } 506 507 static void 508 swrand_add_entropy_later(uint8_t *ptr, size_t len) 509 { 510 mutex_enter(&buffer_lock); 511 swrand_add_bytes_later(ptr, len); 512 mutex_exit(&buffer_lock); 513 } 514 515 static void 516 swrand_add_entropy(uint8_t *ptr, size_t len, uint16_t entropy_est) 517 { 518 mutex_enter(&srndpool_lock); 519 swrand_add_bytes(ptr, len); 520 swrand_mix_pool(entropy_est); 521 mutex_exit(&srndpool_lock); 522 } 523 524 /* 525 * The physmem_* routines below generate entropy by reading blocks of 526 * physical memory. Entropy is gathered in a couple of ways: 527 * 528 * - By reading blocks of physical memory and detecting if changes 529 * occurred in the blocks read. 530 * 531 * - By measuring the time it takes to load and hash a block of memory 532 * and computing the differences in the measured time. 533 * 534 * The first method was used in the CryptoRand implementation. Physical 535 * memory is divided into blocks of fixed size. A block of memory is 536 * chosen from the possible blocks and hashed to produce a digest. This 537 * digest is then mixed into the pool. A single bit from the digest is 538 * used as a parity bit or "checksum" and compared against the previous 539 * "checksum" computed for the block. If the single-bit checksum has not 540 * changed, no entropy is credited to the pool. If there is a change, 541 * then the assumption is that at least one bit in the block has changed. 542 * The possible locations within the memory block of where the bit change 543 * occurred is used as a measure of entropy. For example, if a block 544 * size of 4096 bytes is used, about log_2(4096*8)=15 bits worth of 545 * entropy is available. Because the single-bit checksum will miss half 546 * of the changes, the amount of entropy credited to the pool is doubled 547 * when a change is detected. With a 4096 byte block size, a block 548 * change will add a total of 30 bits of entropy to the pool. 549 * 550 * The second method measures the amount of time it takes to read and 551 * hash a physical memory block (as described above). The time measured 552 * can vary depending on system load, scheduling and other factors. 553 * Differences between consecutive measurements are computed to come up 554 * with an entropy estimate. The first, second, and third order delta is 555 * calculated to determine the minimum delta value. The number of bits 556 * present in this minimum delta value is the entropy estimate. This 557 * entropy estimation technique using time deltas is similar to that used 558 * in /dev/random implementations from Linux/BSD. 559 */ 560 561 static int 562 physmem_ent_init(physmem_entsrc_t *entsrc) 563 { 564 uint8_t *ptr; 565 int i; 566 567 bzero(entsrc, sizeof (*entsrc)); 568 569 /* 570 * The maximum entropy amount in bits per block of memory read is 571 * log_2(MEMBLOCKSIZE * 8); 572 */ 573 i = MEMBLOCKSIZE << 3; 574 while (i >>= 1) 575 entsrc->entperblock++; 576 577 /* Initialize entsrc->nblocks */ 578 physmem_count_blocks(); 579 580 if (entsrc->nblocks == 0) { 581 cmn_err(CE_WARN, "no memory blocks to scan!"); 582 return (-1); 583 } 584 585 /* Allocate space for the parity vector and memory page */ 586 entsrc->parity = kmem_alloc(howmany(entsrc->nblocks, 8), 587 KM_SLEEP); 588 entsrc->pmbuf = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP); 589 590 591 /* Initialize parity vector with bits from the pool */ 592 i = howmany(entsrc->nblocks, 8); 593 ptr = entsrc->parity; 594 while (i > 0) { 595 if (i > RNDPOOLSIZE) { 596 bcopy(srndpool, ptr, RNDPOOLSIZE); 597 mutex_enter(&srndpool_lock); 598 swrand_mix_pool(0); 599 mutex_exit(&srndpool_lock); 600 ptr += RNDPOOLSIZE; 601 i -= RNDPOOLSIZE; 602 } else { 603 bcopy(srndpool, ptr, i); 604 break; 605 } 606 } 607 608 /* Generate some entropy to further initialize the pool */ 609 mutex_enter(&srndpool_lock); 610 physmem_ent_gen(entsrc); 611 entropy_bits = 0; 612 mutex_exit(&srndpool_lock); 613 614 return (0); 615 } 616 617 static void 618 physmem_ent_fini(physmem_entsrc_t *entsrc) 619 { 620 if (entsrc->pmbuf != NULL) 621 vmem_free(heap_arena, entsrc->pmbuf, PAGESIZE); 622 if (entsrc->parity != NULL) 623 kmem_free(entsrc->parity, howmany(entsrc->nblocks, 8)); 624 bzero(entsrc, sizeof (*entsrc)); 625 } 626 627 static void 628 physmem_ent_gen(physmem_entsrc_t *entsrc) 629 { 630 struct memlist *pmem; 631 offset_t offset, poffset; 632 pfn_t pfn; 633 int i, nbytes, len, ent = 0; 634 uint32_t block, oblock; 635 hrtime_t ts1, ts2, diff, delta, delta2, delta3; 636 uint8_t digest[HASHSIZE]; 637 HASH_CTX ctx; 638 639 /* 640 * Use each 32-bit quantity in the pool to pick a memory 641 * block to read. 642 */ 643 for (i = 0; i < RNDPOOLSIZE/4; i++) { 644 645 /* If the pool is "full", stop after one block */ 646 if (entropy_bits + ent >= RNDPOOLSIZE * 8) { 647 if (i > 0) 648 break; 649 } 650 651 /* 652 * This lock protects reading of phys_install. 653 * Any changes to this list, by DR, are done while 654 * holding this lock. So, holding this lock is sufficient 655 * to handle DR also. 656 */ 657 memlist_read_lock(); 658 659 /* We're left with less than 4K of memory after DR */ 660 ASSERT(entsrc->nblocks > 0); 661 662 /* Pick a memory block to read */ 663 block = oblock = srndpool[i] % entsrc->nblocks; 664 665 for (pmem = phys_install; pmem != NULL; pmem = pmem->next) { 666 if (block < pmem->size / MEMBLOCKSIZE) 667 break; 668 block -= pmem->size / MEMBLOCKSIZE; 669 } 670 671 ASSERT(pmem != NULL); 672 673 offset = pmem->address + block * MEMBLOCKSIZE; 674 675 if (!address_in_memlist(phys_install, offset, MEMBLOCKSIZE)) { 676 memlist_read_unlock(); 677 continue; 678 } 679 680 /* 681 * Figure out which page to load to read the 682 * memory block. Load the page and compute the 683 * hash of the memory block. 684 */ 685 len = MEMBLOCKSIZE; 686 ts1 = gethrtime(); 687 HashInit(&ctx); 688 while (len) { 689 pfn = offset >> PAGESHIFT; 690 poffset = offset & PAGEOFFSET; 691 nbytes = PAGESIZE - poffset < len ? 692 PAGESIZE - poffset : len; 693 694 hat_devload(kas.a_hat, entsrc->pmbuf, 695 PAGESIZE, pfn, PROT_READ, 696 HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK); 697 698 HashUpdate(&ctx, (uint8_t *)entsrc->pmbuf + poffset, 699 nbytes); 700 701 hat_unload(kas.a_hat, entsrc->pmbuf, PAGESIZE, 702 HAT_UNLOAD_UNLOCK); 703 704 len -= nbytes; 705 offset += nbytes; 706 } 707 /* We got our pages. Let the DR roll */ 708 memlist_read_unlock(); 709 710 HashFinal(digest, &ctx); 711 ts2 = gethrtime(); 712 713 /* 714 * Compute the time it took to load and hash the 715 * block and compare it against the previous 716 * measurement. The delta of the time values 717 * provides a small amount of entropy. The 718 * minimum of the first, second, and third order 719 * delta is used to estimate how much entropy 720 * is present. 721 */ 722 diff = ts2 - ts1; 723 delta = diff - entsrc->last_diff; 724 if (delta < 0) 725 delta = -delta; 726 delta2 = delta - entsrc->last_delta; 727 if (delta2 < 0) 728 delta2 = -delta2; 729 delta3 = delta2 - entsrc->last_delta2; 730 if (delta3 < 0) 731 delta3 = -delta3; 732 entsrc->last_diff = diff; 733 entsrc->last_delta = delta; 734 entsrc->last_delta2 = delta2; 735 736 if (delta > delta2) 737 delta = delta2; 738 if (delta > delta3) 739 delta = delta3; 740 delta2 = 0; 741 while (delta >>= 1) 742 delta2++; 743 ent += delta2; 744 745 /* 746 * If the memory block has changed, credit the pool with 747 * the entropy estimate. The entropy estimate is doubled 748 * because the single-bit checksum misses half the change 749 * on average. 750 */ 751 if (physmem_parity_update(entsrc->parity, oblock, 752 digest[0] & 1)) 753 ent += 2 * entsrc->entperblock; 754 755 /* Add the entropy bytes to the pool */ 756 swrand_add_bytes(digest, HASHSIZE); 757 swrand_add_bytes((uint8_t *)&ts1, sizeof (ts1)); 758 swrand_add_bytes((uint8_t *)&ts2, sizeof (ts2)); 759 } 760 761 swrand_mix_pool(ent); 762 } 763 764 static int 765 physmem_parity_update(uint8_t *parity_vec, uint32_t block, int parity) 766 { 767 /* Test and set the parity bit, return 1 if changed */ 768 if (parity == ((parity_vec[block >> 3] >> (block & 7)) & 1)) 769 return (0); 770 parity_vec[block >> 3] ^= 1 << (block & 7); 771 return (1); 772 } 773 774 /* Compute number of memory blocks available to scan */ 775 static void 776 physmem_count_blocks() 777 { 778 struct memlist *pmem; 779 780 memlist_read_lock(); 781 entsrc.nblocks = 0; 782 for (pmem = phys_install; pmem != NULL; pmem = pmem->next) { 783 entsrc.nblocks += pmem->size / MEMBLOCKSIZE; 784 if (entsrc.nblocks > MAXMEMBLOCKS) { 785 entsrc.nblocks = MAXMEMBLOCKS; 786 break; 787 } 788 } 789 memlist_read_unlock(); 790 } 791 792 /* 793 * Dynamic Reconfiguration call-back functions 794 */ 795 796 /* ARGSUSED */ 797 static void 798 rnd_dr_callback_post_add(void *arg, pgcnt_t delta) 799 { 800 /* More memory is available now, so update entsrc->nblocks. */ 801 physmem_count_blocks(); 802 } 803 804 /* Call-back routine invoked before the DR starts a memory removal. */ 805 /* ARGSUSED */ 806 static int 807 rnd_dr_callback_pre_del(void *arg, pgcnt_t delta) 808 { 809 return (0); 810 } 811 812 /* Call-back routine invoked after the DR starts a memory removal. */ 813 /* ARGSUSED */ 814 static void 815 rnd_dr_callback_post_del(void *arg, pgcnt_t delta, int cancelled) 816 { 817 /* Memory has shrunk, so update entsrc->nblocks. */ 818 physmem_count_blocks(); 819 } 820 821 /* Timeout handling to gather entropy from physmem events */ 822 static void 823 swrand_schedule_timeout(void) 824 { 825 clock_t ut; /* time in microseconds */ 826 827 ASSERT(MUTEX_HELD(&srndpool_lock)); 828 /* 829 * The new timeout value is taken from the pool of random bits. 830 * We're merely reading the first 32 bits from the pool here, not 831 * consuming any entropy. 832 * This routine is usually called right after stirring the pool, so 833 * srndpool[0] will have a *fresh* random value each time. 834 * The timeout multiplier value is a random value between 0.7 sec and 835 * 1.748575 sec (0.7 sec + 0xFFFFF microseconds). 836 * The new timeout is TIMEOUT_INTERVAL times that multiplier. 837 */ 838 ut = 700000 + (clock_t)(srndpool[0] & 0xFFFFF); 839 rnd_timeout_id = timeout(rnd_handler, NULL, 840 TIMEOUT_INTERVAL * drv_usectohz(ut)); 841 } 842 843 /*ARGSUSED*/ 844 static void 845 rnd_handler(void *arg) 846 { 847 mutex_enter(&srndpool_lock); 848 849 physmem_ent_gen(&entsrc); 850 if (snum_waiters > 0) 851 cv_broadcast(&srndpool_read_cv); 852 swrand_schedule_timeout(); 853 854 mutex_exit(&srndpool_lock); 855 } 856