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