summaryrefslogtreecommitdiff
path: root/sys/dev/random
Commit message (Collapse)AuthorAgeFilesLines
* random(4) FenestrasX: Push root seed version to arc4random(3)Conrad Meyer2020-10-102-1/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | Push the root seed version to userspace through the VDSO page, if the RANDOM_FENESTRASX algorithm is enabled. Otherwise, there is no functional change. The mechanism can be disabled with debug.fxrng_vdso_enable=0. arc4random(3) obtains a pointer to the root seed version published by the kernel in the shared page at allocation time. Like arc4random(9), it maintains its own per-process copy of the seed version corresponding to the root seed version at the time it last rekeyed. On read requests, the process seed version is compared with the version published in the shared page; if they do not match, arc4random(3) reseeds from the kernel before providing generated output. This change does not implement the FenestrasX concept of PCPU userspace generators seeded from a per-process base generator. That change is left for future discussion/work. Reviewed by: kib (previous version) Approved by: csprng (me -- only touching FXRNG here) Differential Revision: https://reviews.freebsd.org/D22839 Notes: svn path=/head/; revision=366622
* arc4random(9): Integrate with RANDOM_FENESTRASX push-reseedConrad Meyer2020-10-106-3/+81
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There is no functional change for the existing Fortuna random(4) implementation, which remains the default in GENERIC. In the FenestrasX model, when the root CSPRNG is reseeded from pools due to an (infrequent) timer, child CSPRNGs can cheaply detect this condition and reseed. To do so, they just need to track an additional 64-bit value in the associated state, and compare it against the root seed version (generation) on random reads. This revision integrates arc4random(9) into that model without substantially changing the design or implementation of arc4random(9). The motivation is that arc4random(9) is immediately reseeded when the backing random(4) implementation has additional entropy. This is arguably most important during boot, when fenestrasX is reseeding at 1, 3, 9, 27, etc., second intervals. Today, arc4random(9) has a hardcoded 300 second reseed window. Without this mechanism, if arc4random(9) gets weak entropy during initial seed (and arc4random(9) is used early in boot, so this is quite possible), it may continue to emit poorly seeded output for 5 minutes. The FenestrasX push-reseed scheme corrects consumers, like arc4random(9), as soon as possible. Reviewed by: markm Approved by: csprng (markm) Differential Revision: https://reviews.freebsd.org/D22838 Notes: svn path=/head/; revision=366621
* Add "Fenestras X" alternative /dev/random implementationConrad Meyer2020-10-109-0/+1728
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fortuna remains the default; no functional change to GENERIC. Big picture: - Scalable entropy generation with per-CPU, buffered local generators. - "Push" system for reseeding child generators when root PRNG is reseeded. (Design can be extended to arc4random(9) and userspace generators.) - Similar entropy pooling system to Fortuna, but starts with a single pool to quickly bootstrap as much entropy as possible early on. - Reseeding from pooled entropy based on time schedule. The time interval starts small and grows exponentially until reaching a cap. Again, the goal is to have the RNG state depend on as much entropy as possible quickly, but still periodically incorporate new entropy for the same reasons as Fortuna. Notable design choices in this implementation that differ from those specified in the whitepaper: - Blake2B instead of SHA-2 512 for entropy pooling - Chacha20 instead of AES-CTR DRBG - Initial seeding. We support more platforms and not all of them use loader(8). So we have to grab the initial entropy sources in kernel mode instead, as much as possible. Fortuna didn't have any mechanism for this aside from the special case of loader-provided previous-boot entropy, so most of these sources remain TODO after this commit. Reviewed by: markm Approved by: csprng (markm) Differential Revision: https://reviews.freebsd.org/D22837 Notes: svn path=/head/; revision=366620
* Use zfree() instead of explicit_bzero() and free().John Baldwin2020-06-251-2/+1
| | | | | | | | | | | | | | | In addition to reducing lines of code, this also ensures that the full allocation is always zeroed avoiding possible bugs with incorrect lengths passed to explicit_bzero(). Suggested by: cem Reviewed by: cem, delphij Approved by: csprng (cem) Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D25435 Notes: svn path=/head/; revision=362624
* Remove ubsec(4).John Baldwin2020-05-111-1/+0
| | | | | | | | | | | | This driver was previously marked for deprecation in r360710. Approved by: csprng (cem, gordon, delphij) Relnotes: yes Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D24766 Notes: svn path=/head/; revision=360918
* Mark more nodes as CTLFLAG_MPSAFE or CTLFLAG_NEEDGIANT (18 of many)Pawel Biernacki2020-02-274-15/+20
| | | | | | | | | | | | | | | | | | | r357614 added CTLFLAG_NEEDGIANT to make it easier to find nodes that are still not MPSAFE (or already are but aren’t properly marked). Use it in preparation for a general review of all nodes. This is non-functional change that adds annotations to SYSCTL_NODE and SYSCTL_PROC nodes using one of the soon-to-be-required flags. Mark all obvious cases as MPSAFE. All entries that haven't been marked as MPSAFE before are by default marked as NEEDGIANT Reviewed by: cem Approved by: csprng, kib (mentor, blanket) Differential Revision: https://reviews.freebsd.org/D23841 Notes: svn path=/head/; revision=358379
* vmgenid(4): Integrate as a random(4) sourceConrad Meyer2020-01-012-0/+8
| | | | | | | | | | | The number is public and has no "entropy," but should be integrated quickly on VM rewind events to avoid duplicate sequences. Approved by: csprng(markm) Differential Revision: https://reviews.freebsd.org/D22946 Notes: svn path=/head/; revision=356245
* random(4): Make entropy source deregistration safeConrad Meyer2019-12-301-10/+50
| | | | | | | | | | | | | | | | | | | | | | | | | Allow loadable modules that provide random entropy source(s) to safely unload. Prior to this change, no driver could ensure that their random_source structure was not being used by random_harvestq.c for any period of time after invoking random_source_deregister(). This change converts the source_list LIST to a ConcurrencyKit CK_LIST and uses an epoch(9) to protect typical read accesses of the list. The existing HARVEST_LOCK spin mutex is used to safely add and remove list entries. random_source_deregister() uses epoch_wait() to ensure no concurrent source_list readers are accessing a random_source before freeing the list item and returning to the caller. Callers can safely unload immediately after random_source_deregister() returns. Reviewed by: markj Approved by: csprng(markm) Discussed with: jhb Differential Revision: https://reviews.freebsd.org/D22489 Notes: svn path=/head/; revision=356194
* random(4): Simplify RANDOM_LOADABLEConrad Meyer2019-12-266-229/+59
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Simplify RANDOM_LOADABLE by removing the ability to unload a LOADABLE random(4) implementation. This allows one-time random module selection at boot, by loader(8). Swapping modules on the fly doesn't seem especially useful. This removes the need to hold a lock over the sleepable module calls read_random and read_random_uio. init/deinit have been pulled out of random_algorithm entirely. Algorithms can run their own sysinits to initialize; deinit is removed entirely, as algorithms can not be unloaded. Algorithms should initialize at SI_SUB_RANDOM:SI_ORDER_SECOND. In LOADABLE systems, algorithms install a pointer to their local random_algorithm context in p_random_alg_context at that time. Go ahead and const'ify random_algorithm objects; there is no need to mutate them at runtime. LOADABLE kernel NULL checks are removed from random_harvestq by ordering random_harvestq initialization at SI_SUB_RANDOM:SI_ORDER_THIRD, after algorithm init. Prior to random_harvestq init, hc_harvest_mask is zero and no events are forwarded to algorithms; after random_harvestq init, the relevant pointers will already have been installed. Remove the bulk of random_infra shim wrappers and instead expose the bare function pointers in sys/random.h. In LOADABLE systems, read_random(9) et al are just thin shim macros around invoking the associated function pointer. We do not provide a registration system but instead expect LOADABLE modules to register themselves at SI_SUB_RANDOM:SI_ORDER_SECOND. An example is provided in randomdev.c, as used in the random_fortuna.ko module. Approved by: csprng(markm) Discussed with: gordon Differential Revision: https://reviews.freebsd.org/D22512 Notes: svn path=/head/; revision=356096
* random(4): Flip default Fortuna generator over to Chacha20Conrad Meyer2019-12-201-6/+6
| | | | | | | | | | | | | | | | The implementation was landed in r344913 and has had some bake time (at least on my personal systems). There is some discussion of the motivation for defaulting to this cipher as a PRF in the commit log for r344913. As documented in that commit, administrators can retain the prior (AES-ICM) mode of operation by setting the 'kern.random.use_chacha20_cipher' tunable to 0 in loader.conf(5). Approved by: csprng(delphij, markm) Differential Revision: https://reviews.freebsd.org/D22878 Notes: svn path=/head/; revision=355949
* random(4): Fortuna: Enable concurrent generation by default for 13Conrad Meyer2019-12-201-12/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | Flip the knob added in r349154 to "enabled." The commit message from that revision and associated code comment describe the rationale, implementation, and motivation for the new default in detail. I have dog-fooded this configuration on my own systems for six months, for what that's worth. For end-users: the result is just as secure. The benefit is a faster, more responsive system when processes produce significant demand on random(4). As mentioned in the earlier commit, the prior behavior may be restored by setting the kern.random.fortuna.concurrent_read="0" knob in loader.conf(5). This scales the random generation side of random(4) somewhat, although there is still a global mutex being shared by all cores and rand_harvestq; the situation is generally much better than it was before on small CPU systems, but do not expect miracles on 256-core systems running 256-thread full-rate random(4) read. Work is ongoing to address both the generation-side (in more depth) and the harvest-side scaling problems. Approved by: csprng(delphij, markm) Tested by: markm Differential Revision: https://reviews.freebsd.org/D22879 Notes: svn path=/head/; revision=355930
* random(4): De-export random_sources listConrad Meyer2019-11-223-10/+8
| | | | | | | | | | | | | The internal datastructures do not need to be visible outside of random_harvestq, and this helps ensure they are not misused. No functional change. Approved by: csprng(delphij, markm) Differential Revision: https://reviews.freebsd.org/D22485 Notes: svn path=/head/; revision=355022
* random(4): Use ordinary sysctl definitionsConrad Meyer2019-11-221-23/+11
| | | | | | | | | | | | There's no need to dynamically populate them; the SYSCTL_ macros take care of load/unload appropriately already (and random_harvestq is 'standard' and cannot be unloaded anyway). Approved by: csprng(delphij, markm) Differential Revision: https://reviews.freebsd.org/D22484 Notes: svn path=/head/; revision=355020
* random(4): Abstract loader entropy injectionConrad Meyer2019-11-221-30/+59
| | | | | | | | | | | | | | Break random_harvestq_prime up into some logical subroutines. The goal is that it becomes easier to add other early entropy sources. While here, drop pre-12.0 compatibility logic. loader default configuration should preload the file as expeced since 12.0. Approved by: csprng(delphij, markm) Differential Revision: https://reviews.freebsd.org/D22482 Notes: svn path=/head/; revision=355018
* random(4): Remove unused definitionsConrad Meyer2019-11-221-3/+0
| | | | | | | | Approved by: csprng(gordon, markm) Differential Revision: https://reviews.freebsd.org/D22481 Notes: svn path=/head/; revision=355017
* random/ivy: Provide mechanism to read independent seed values from rdrandConrad Meyer2019-11-221-11/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On x86 platforms with the intrinsic, rdrand is a deterministic bit generator (AES-CTR) seeded from an entropic source. On x86 platforms with rdseed, it is something closer to the upstream entropic source. (There is more nuance; a block diagram is provided in [1].) On devices with rdrand and without rdseed, there is no good intrinsic for acecssing the good entropic soure directly. However, the DRBG is guaranteed to reseed every 8 kB on these platforms. As a conservative option, on such hardware we can read an extra 7.99kB samples every time we want a sample from an independent seed. As one can imagine, this drastically slows the effective read rate of RDRAND (a factor of 1024 on amd64 and 2048 on ia32). Microbenchmarks on AMD Zen (has RDSEED) show an RDRAND rate of 25 MB/s and Intel Haswell (no RDSEED) show RDRAND of 170 MB/s. This would reduce the read rate on Haswell to ~170 kB/s (at 100% CPU). random(4)'s harvestq thread periodically "feeds" from pure sources in amounts of 128-1024 bytes. On Haswell, enabling this feature increases the CPU time of RDRAND in each "feed" from approximately 0.7-6 µs to 0.7-6 ms. Because there is some performance penalty to this more conservative option, a knob is provided to enable the change. The change does not affect platforms with RDSEED. [1]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide#inpage-nav-4-2 Approved by: csprng(delphij, markm) Differential Revision: https://reviews.freebsd.org/D22455 Notes: svn path=/head/; revision=355014
* random/ivy: Trivial refactoringConrad Meyer2019-11-201-7/+7
| | | | | | | | | | | | | It is clearer to me to return success/error (true/false) instead of some retry count linked to the inline assembly implementation. No functional change. Approved by: core(csprng) => csprng(markm) Differential Revision: https://reviews.freebsd.org/D22454 Notes: svn path=/head/; revision=354913
* random(4): Reorder configuration of random source modulesConrad Meyer2019-08-185-63/+81
| | | | | | | | | | | | | | | | | | | Move fast entropy source registration to the earlier SI_SUB_RANDOM:SI_ORDER_FOURTH and move random_harvestq_prime after that. Relocate the registration routines out of the much later randomdev module and into random_harvestq. This is necessary for the fast random sources to actually register before we perform random_harvestq_prime() early in the kernel boot. No functional change. Reviewed by: delphij, markjm Approved by: secteam(delphij) Differential Revision: https://reviews.freebsd.org/D21308 Notes: svn path=/head/; revision=351191
* random(4): Remove "EXPERIMENTAL" verbiage from concurrent operationConrad Meyer2019-08-151-9/+105
| | | | | | | | | | | | | | | | | | | | | | | | No functional change. Add a verbose comment giving an example side-by-side comparison between the prior and Concurrent modes of Fortuna, and why one should believe they produce the same result. The intent is to flip this on by default prior to 13.0, so testing is encouraged. To enable, add the following to loader.conf: kern.random.fortuna.concurrent_read="1" The intent is also to flip the default blockcipher to the faster Chacha-20 prior to 13.0, so testing of that mode of operation is also appreciated. To enable, add the following to loader.conf: kern.random.use_chacha20_cipher="1" Approved by: secteam(implicit) Notes: svn path=/head/; revision=351062
* random(4): Fix a regression in short AES mode readsConrad Meyer2019-06-181-1/+1
| | | | | | | | | | | | | | In r349154, random device reads of size < 16 bytes (AES block size) were accidentally broken to loop forever. Correct the loop condition for small reads. Reported by: pho Reviewed by: delphij Approved by: secteam(delphij) Differential Revision: https://reviews.freebsd.org/D20686 Notes: svn path=/head/; revision=349176
* random(4): Fortuna: allow increased concurrencyConrad Meyer2019-06-175-91/+291
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add experimental feature to increase concurrency in Fortuna. As this diverges slightly from canonical Fortuna, and due to the security sensitivity of random(4), it is off by default. To enable it, set the tunable kern.random.fortuna.concurrent_read="1". The rest of this commit message describes the behavior when enabled. Readers continue to update shared Fortuna state under global mutex, as they do in the status quo implementation of the algorithm, but shift the actual PRF generation out from under the global lock. This massively reduces the CPU time readers spend holding the global lock, allowing for increased concurrency on SMP systems and less bullying of the harvestq kthread. It is somewhat of a deviation from FS&K. I think the primary difference is that the specific sequence of AES keys will differ if READ_RANDOM_UIO is accessed concurrently (as the 2nd thread to take the mutex will no longer receive a key derived from rekeying the first thread). However, I believe the goals of rekeying AES are maintained: trivially, we continue to rekey every 1MB for the statistical property; and each consumer gets a forward-secret, independent AES key for their PRF. Since Chacha doesn't need to rekey for sequences of any length, this change makes no difference to the sequence of Chacha keys and PRF generated when Chacha is used in place of AES. On a GENERIC 4-thread VM (so, INVARIANTS/WITNESS, numbers not necessarily representative), 3x concurrent AES performance jumped from ~55 MiB/s per thread to ~197 MB/s per thread. Concurrent Chacha20 at 3 threads went from roughly ~113 MB/s per thread to ~430 MB/s per thread. Prior to this change, the system was extremely unresponsive with 3-4 concurrent random readers; each thread had high variance in latency and throughput, depending on who got lucky and won the lock. "rand_harvestq" thread CPU use was high (double digits), seemingly due to spinning on the global lock. After the change, concurrent random readers and the system in general are much more responsive, and rand_harvestq CPU use dropped to basically zero. Tests are added to the devrandom suite to ensure the uint128_add64 primitive utilized by unlocked read functions to specification. Reviewed by: markm Approved by: secteam(delphij) Relnotes: yes Differential Revision: https://reviews.freebsd.org/D20313 Notes: svn path=/head/; revision=349154
* random(4): Generalize algorithm-independent APIsConrad Meyer2019-06-176-112/+189
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | At a basic level, remove assumptions about the underlying algorithm (such as output block size and reseeding requirements) from the algorithm-independent logic in randomdev.c. Chacha20 does not have many of the restrictions that AES-ICM does as a PRF (Pseudo-Random Function), because it has a cipher block size of 512 bits. The motivation is that by generalizing the API, Chacha is not penalized by the limitations of AES. In READ_RANDOM_UIO, first attempt to NOWAIT allocate a large enough buffer for the entire user request, or the maximal input we'll accept between signal checking, whichever is smaller. The idea is that the implementation of any randomdev algorithm is then free to divide up large requests in whatever fashion it sees fit. As part of this, two responsibilities from the "algorithm-generic" randomdev code are pushed down into the Fortuna ra_read implementation (and any other future or out-of-tree ra_read implementations): 1. If an algorithm needs to rekey every N bytes, it is responsible for handling that in ra_read(). (I.e., Fortuna's 1MB rekey interval for AES block generation.) 2. If an algorithm uses a block cipher that doesn't tolerate partial-block requests (again, e.g., AES), it is also responsible for handling that in ra_read(). Several APIs are changed from u_int buffer length to the more canonical size_t. Several APIs are changed from taking a blockcount to a bytecount, to permit PRFs like Chacha20 to directly generate quantities of output that are not multiples of RANDOM_BLOCKSIZE (AES block size). The Fortuna algorithm is changed to NOT rekey every 1MiB when in Chacha20 mode (kern.random.use_chacha20_cipher="1"). This is explicitly supported by the math in FS&K §9.4 (Ferguson, Schneier, and Kohno; "Cryptography Engineering"), as well as by their conclusion: "If we had a block cipher with a 256-bit [or greater] block size, then the collisions would not have been an issue at all." For now, continue to break up reads into PAGE_SIZE chunks, as they were before. So, no functional change, mostly. Reviewed by: markm Approved by: secteam(delphij) Differential Revision: https://reviews.freebsd.org/D20312 Notes: svn path=/head/; revision=349138
* random(4): Add regression tests for uint128 implementation, Chacha CTRConrad Meyer2019-06-172-2/+6
| | | | | | | | | | | | | | | | | | | | Add some basic regression tests to verify behavior of both uint128 implementations at typical boundary conditions, to run on all architectures. Test uint128 increment behavior of Chacha in keystream mode, as used by 'kern.random.use_chacha20_cipher=1' (r344913) to verify assumptions at edge cases. These assumptions are critical to the safety of using Chacha as a PRF in Fortuna (as implemented). (Chacha's use in arc4random is safe regardless of these tests, as it is limited to far less than 4 billion blocks of output in that API.) Reviewed by: markm Approved by: secteam(gordon) Differential Revision: https://reviews.freebsd.org/D20392 Notes: svn path=/head/; revision=349137
* random(4): Fix RANDOM_LOADABLE buildConrad Meyer2019-06-011-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I introduced an obvious compiler error in r346282, so this change fixes that. Unfortunately, RANDOM_LOADABLE isn't covered by our existing tinderbox, and it seems like there were existing latent linking problems. I believe these were introduced on accident in r338324 during reduction of the boolean expression(s) adjacent to randomdev.c and hash.c. It seems the RANDOM_LOADABLE build breakage has gone unnoticed for nine months. This change correctly annotates randomdev.c and hash.c with !random_loadable to match the pre-r338324 logic; and additionally updates the HWRNG drivers in MD 'files.*', which depend on random_device symbols, with !random_loadable (it is invalid for the kernel to depend on symbols from a module). (The expression for both randomdev.c and hash.c was the same, prior to r338324: "optional random random_yarrow | random !random_yarrow !random_loadable". I.e., "random && (yarrow || !loadable)." When Yarrow was removed ("yarrow := False"), the expression was incorrectly reduced to "optional random" when it should have retained "random && !loadable".) Additionally, I discovered that virtio_random was missing a MODULE_DEPEND on random_device, which breaks kld load/link of the driver on RANDOM_LOADABLE kernels. Address that issue as well. PR: 238223 Reported by: Eir Nym <eirnym AT gmail.com> Reviewed by: delphij, markm Approved by: secteam(delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D20466 Notes: svn path=/head/; revision=348489
* random(4): deduplicate explicit_bzero() in harvestConrad Meyer2019-05-233-4/+2
| | | | | | | | | | | | | | | | | | | | | Pull the responsibility for zeroing events, which is general to any conceivable implementation of a random device algorithm, out of the algorithm-specific Fortuna code and into the callers. Most callers indirect through random_fortuna_process_event(), so add the logic there. Most callers already explicitly bzeroed the events they provided, so the logic in Fortuna was mostly redundant. Add one missing bzero in randomdev_accumulate(). Also, remove a redundant bzero in the same function -- randomdev_hash_finish() is obliged to bzero the hash state. Reviewed by: delphij Approved by: secteam(delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D20318 Notes: svn path=/head/; revision=348199
* Remove resolver_qual from DEFINE_IFUNC/DEFINE_UIFUNC macros.Konstantin Belousov2019-05-161-1/+1
| | | | | | | | | | | | | In all practical situations, the resolver visibility is static. Requested by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Approved by: so (emaste) Differential revision: https://reviews.freebsd.org/D20281 Notes: svn path=/head/; revision=347895
* Fortuna: Fix false negatives in is_random_seeded()Conrad Meyer2019-05-131-5/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (1) We may have had sufficient entropy to consider Fortuna seeded, but the random_fortuna_seeded() function would produce a false negative if fs_counter was still zero. This condition could arise after random_harvestq_prime() processed the /boot/entropy file and before any read-type operation invoked "pre_read()." Fortuna's fs_counter variable is only incremented (if certain conditions are met) by reseeding, which is invoked by random_fortuna_pre_read(). is_random_seeded(9) was introduced in r346282, but the function was unused prior to r346358, which introduced this regression. The regression broke initial seeding of arc4random(9) and broke periodic reseeding[A], until something other than arc4random(9) invoked read_random(9) or read_random_uio(9) directly. (Such as userspace getrandom(2) or read(2) of /dev/random. By default, /etc/rc.d/random does this during multiuser start-up.) (2) The conditions under which Fortuna will reseed (including initial seeding) are: (a) sufficient "entropy" (by sheer byte count; default 64) is collected in the zeroth pool (of 32 pools), and (b) it has been at least 100ms since the last reseed (to prevent trivial DoS; part of FS&K design). Prior to this revision, initial seeding might have been prevented if the reseed function was invoked during the first 100ms of boot. This revision addresses both of these issues. If random_fortuna_seeded() observes a zero fs_counter, it invokes random_fortuna_pre_read() and checks again. This addresses the problem where entropy actually was sufficient, but nothing had attempted a read -> pre_read yet. The second change is to disable the 100ms reseed guard when Fortuna has never been seeded yet (fs_lasttime == 0). The guard is intended to prevent gratuitous subsequent reseeds, not initial seeding! Machines running CURRENT between r346358 and this revision are encouraged to refresh when possible. Keys generated by userspace with /dev/random or getrandom(9) during this timeframe are safe, but any long-term session keys generated by kernel arc4random consumers are potentially suspect. [A]: Broken in the sense that is_random_seeded(9) false negatives would cause arc4random(9) to (re-)seed with weak entropy (SHA256(cyclecount || FreeBSD_version)). PR: 237869 Reported by: delphij, dim Reviewed by: delphij Approved by: secteam(delphij) X-MFC-With: r346282, r346358 (if ever) Security: yes Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D20239 Notes: svn path=/head/; revision=347546
* Avoid returning a NULL pointer from the Intel hw PRNG ifunc resolver.Mark Johnston2019-05-101-1/+8
| | | | | | | | | | | | | | DTrace expects kernel function symbols of a non-zero size to have an implementation, which is a reasonable invariant to preserve. Reported and tested by: ler Reviewed by: cem, kib Approved by: so (delphij) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D20218 Notes: svn path=/head/; revision=347423
* random(4): Don't complain noisily when an entropy source is slowConrad Meyer2019-05-081-7/+11
| | | | | | | | | | | | | | | | | | | | | | Mjg@ reports that RDSEED (r347239) causes a lot of logspam from this printf, and I don't feel that it is especially useful (even ratelimited). There are many other quality/quantity checks we're not performing on entropy sources; lack of high frequency availability does not disqualify a good entropy source. There is some discussion in the linked Differential about what logging might be appropriate and/or polling policy for slower TRNG sources. Please feel free to chime in if you have opinions. Reported by: mjg Reviewed by: markm, delphij Approved by: secteam(delphij) X-MFC-With: r347239 Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D20195 Notes: svn path=/head/; revision=347329
* random: x86 driver: Prefer RDSEED over RDRAND when availableConrad Meyer2019-05-081-9/+39
| | | | | | | | | | | | | | | | | Per https://software.intel.com/en-us/blogs/2012/11/17/the-difference-between-rdrand-and-rdseed , RDRAND is a PRNG seeded from the same source as RDSEED. The source is more suitable as PRNG seed material, so prefer it when the RDSEED intrinsic is available (indicated in CPU feature bits). Reviewed by: delphij, jhb, imp (earlier version) Approved by: secteam(delphij) Security: yes Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D20192 Notes: svn path=/head/; revision=347239
* random(4): Restore availability tradeoff prior to r346250Conrad Meyer2019-04-183-9/+92
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As discussed in that commit message, it is a dangerous default. But the safe default causes enough pain on a variety of platforms that for now, restore the prior default. Some of this is self-induced pain we should/could do better about; for example, programmatic CI systems and VM managers should introduce entropy from the host for individual VM instances. This is considered a future work item. On modern x86 and Power9 systems, this may be wholly unnecessary after D19928 lands (even in the non-ideal case where early /boot/entropy is unavailable), because they have fast hardware random sources available early in boot. But D19928 is not yet landed and we have a host of architectures which do not provide fast random sources. This change adds several tunables and diagnostic sysctls, documented thoroughly in UPDATING and sys/dev/random/random_infra.c. PR: 230875 (reopens) Reported by: adrian, jhb, imp, and probably others Reviewed by: delphij, imp (earlier version), markm (earlier version) Discussed with: adrian Approved by: secteam(delphij) Relnotes: yeah Security: related Differential Revision: https://reviews.freebsd.org/D19944 Notes: svn path=/head/; revision=346358
* random(4): Add is_random_seeded(9) KPIConrad Meyer2019-04-163-3/+34
| | | | | | | | | | | | | | | The imagined use is for early boot consumers of random to be able to make decisions based on whether random is available yet or not. One such consumer seems to be __stack_chk_init(), which runs immediately after random is initialized. A follow-up patch will attempt to address that. Reported by: many Reviewed by: delphij (except man page) Approved by: secteam(delphij) Differential Revision: https://reviews.freebsd.org/D19926 Notes: svn path=/head/; revision=346282
* random(4): Block read_random(9) on initial seedingConrad Meyer2019-04-155-58/+98
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | read_random() is/was used, mostly without error checking, in a lot of very sensitive places in the kernel -- including seeding the widely used arc4random(9). Most uses, especially arc4random(9), should block until the device is seeded rather than proceeding with a bogus or empty seed. I did not spy any obvious kernel consumers where blocking would be inappropriate (in the sense that lack of entropy would be ok -- I did not investigate locking angle thoroughly). In many instances, arc4random_buf(9) or that family of APIs would be more appropriate anyway; that work was done in r345865. A minor cleanup was made to the implementation of the READ_RANDOM function: instead of using a variable-length array on the stack to temporarily store all full random blocks sufficient to satisfy the requested 'len', only store a single block on the stack. This has some benefit in terms of reducing stack usage, reducing memcpy overhead and reducing devrandom output leakage via the stack. Additionally, the stack block is now safely zeroed if it was used. One caveat of this change is that the kern.arandom sysctl no longer returns zero bytes immediately if the random device is not seeded. This means that FreeBSD-specific userspace applications which attempted to handle an unseeded random device may be broken by this change. If such behavior is needed, it can be replaced by the more portable getrandom(2) GRND_NONBLOCK option. On any typical FreeBSD system, entropy is persisted on read/write media and used to seed the random device very early in boot, and blocking is never a problem. This change primarily impacts the behavior of /dev/random on embedded systems with read-only media that do not configure "nodevice random". We toggle the default from 'charge on blindly with no entropy' to 'block indefinitely.' This default is safer, but may cause frustration. Embedded system designers using FreeBSD have several options. The most obvious is to plan to have a small writable NVRAM or NAND to persist entropy, like larger systems. Early entropy can be fed from any loader, or by writing directly to /dev/random during boot. Some embedded SoCs now provide a fast hardware entropy source; this would also work for quickly seeding Fortuna. A 3rd option would be creating an embedded-specific, more simplistic random module, like that designed by DJB in [1] (this design still requires a small rewritable media for forward secrecy). Finally, the least preferred option might be "nodevice random", although I plan to remove this in a subsequent revision. To help developers emulate the behavior of these embedded systems on ordinary workstations, the tunable kern.random.block_seeded_status was added. When set to 1, it blocks the random device. I attempted to document this change in random.4 and random.9 and ran into a bunch of out-of-date or irrelevant or inaccurate content and ended up rototilling those documents more than I intended to. Sorry. I think they're in a better state now. PR: 230875 Reviewed by: delphij, markm (earlier version) Approved by: secteam(delphij), devrandom(markm) Relnotes: yes Differential Revision: https://reviews.freebsd.org/D19744 Notes: svn path=/head/; revision=346250
* Allow using TPM as entropy source.Marcin Wojtas2019-03-231-0/+1
| | | | | | | | | | | | | | | | | TPM has a built-in RNG, with its own entropy source. The driver was extended to harvest 16 random bytes from TPM every 10 seconds. A new build option "TPM_HARVEST" was introduced - for now, however, it is not enabled by default in the GENERIC config. Submitted by: Kornel Duleba <mindal@semihalf.com> Reviewed by: markm, delphij Approved by: secteam Obtained from: Semihalf Sponsored by: Stormshield Differential Revision: https://reviews.freebsd.org/D19620 Notes: svn path=/head/; revision=345438
* Fortuna: Add Chacha20 as an alternative stream cipherConrad Meyer2019-03-084-22/+188
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Chacha20 with a 256 bit key and 128 bit counter size is a good match for an AES256-ICM replacement. In userspace, Chacha20 is typically marginally slower than AES-ICM on machines with AESNI intrinsics, but typically much faster than AES on machines without special intrinsics. ChaCha20 does well on typical modern architectures with SIMD instructions, which includes most types of machines FreeBSD runs on. In the kernel, we can't (or don't) make use of AESNI intrinsics for random(4) anyway. So even on amd64, using Chacha provides a modest performance improvement in random device throughput today. This change makes the stream cipher used by random(4) configurable at boot time with the 'kern.random.use_chacha20_cipher' tunable. Very rough, non-scientific measurements at the /dev/random device, on a GENERIC-NODEBUG amd64 VM with 'pv', show a factor of 2.2x higher throughput for Chacha20 over the existing AES-ICM mode. Reviewed by: delphij, markm Approved by: secteam (delphij) Differential Revision: https://reviews.freebsd.org/D19475 Notes: svn path=/head/; revision=344913
* fortuna: Deduplicate kernel vs user includesConrad Meyer2019-03-011-12/+5
| | | | | | | | | | | | No functional change. Reviewed by: markj, markm Approved by: secteam (delphij), core (brooks) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D19409 Notes: svn path=/head/; revision=344713
* Fortuna: push CTR-mode loop down into randomdev hash.h interfaceConrad Meyer2019-03-013-16/+27
| | | | | | | | | | | | | | | | As a step towards adding other potential streaming ciphers. As well as just pushing the loop down into the rijndael APIs (basically 128-bit wide AES-ICM mode) to eliminate some excess explicit_bzero(). No functional change intended. Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D19411 Notes: svn path=/head/; revision=344710
* random(4): Match enabled sources mask to build optionsConrad Meyer2018-10-271-3/+22
| | | | | | | | | | | | | | | | | | | | | | r287023 and r334450 added build option mechanisms to permanently disable spammy and/or low quality entropy sources. Follow-up those changes by updating the 'enabled' sources mask to match. When sources are compile-time disabled, represent them as disabled in the source mask, and prevent users from modifying that, like pure sources. (Modifying the mask bit would have no effect, but users might think it did if it was not prevented.) Mostly a cosmetic change. Reviewed by: markm Approved by: secteam (gordon) X-MFC-With: 334450 Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D17252 Notes: svn path=/head/; revision=339814
* Fortuna: Add failpoints to simulate initial seeding conditionsConrad Meyer2018-10-261-0/+21
| | | | | | | | | | | | | | | | | | | | | | Set debug.fail_point.random_fortuna_pre_read=return(1) and debug.fail_point.random_fortuna_seeded=return(1) to return to unseeded status (sort of). See the Differential URL for more detail. The goal is to reproduce e.g. Lev's recent CURRENT report[1] about failing newfs arc4random(3) usage (fixed in r338542). No functional change when failpoints are not set. [1]: https://lists.freebsd.org/pipermail/freebsd-current/2018-September/071067.html Reported by: lev Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D17047 Notes: svn path=/head/; revision=339790
* fortuna: Drop global lock to zero stack variablesConrad Meyer2018-10-261-31/+34
| | | | | | | | | | | | | | | Also drop explicit zeroing of hash context -- hash finish() operation is expected to do this. PR: 230877 Suggested by: delphij@ Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16986 Notes: svn path=/head/; revision=339789
* Fortuna: fix a correctness issue in reseed (fortuna_pre_read)Conrad Meyer2018-10-261-1/+1
| | | | | | | | | | | | | | | | | | 'i' counts the number of pools included in the array 's'. Passing 'i+1' to reseed_internal() as the number of blocks in 's' is a bogus overrun of the initialized portion of 's' -- technically UB. I found this via code inspection, referencing §9.5.2 "Pools" of the Fortuna chapter, but I would expect Coverity to notice the same issue. Unfortunately, it doesn't appear to. Reviewed by: markm Approved by: secteam (gordon) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16985 Notes: svn path=/head/; revision=339788
* Fortuna: Fix a race to prevent reseed spammingConrad Meyer2018-10-201-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If multiple threads enter fortuna_pre_read contemporaneously, such as via read(2) or getrandom(2), they could race to check how long it has been since the last update due to a TOCTOU problem with 'now'. Here is an example problematic execution: Thread A: Thread B: now_A = getsbinuptime(); now_B = getsbinuptime(); // now_B > now_A RANDOM_RESEED_LOCK(); if (now - fs_lasttime > SBT_1S/10) { fs_lasttime = now; ... // reseed } RANDOM_RESEED_UNLOCK(); RANDOM_RESEED_LOCK(); if (now_A - fs_lasttime > SBT_1S/10) // now_A - fs_lasttime underflows fs_lasttime = now_A; ... // reseed again, despite less than 100ms elapsing } RANDOM_RESEED_UNLOCK(); To resolve the race, simply check the current time after we win the lock race. If getsbinuptime is perceived to be expensive, another option might be to just accept the race and validate that fs_lasttime isn't "in the future." (It should be within the last ~2^31 seconds out of ~2^32 seconds representable duration.) Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16984 Notes: svn path=/head/; revision=339492
* random(4): Correct a bare zero to the appropriate enumConrad Meyer2018-10-201-1/+2
| | | | | | | | | | | | | | | | | The convention for updating hc_destination[] is to index with a random_entropy_source. Zero happens to match RANDOM_CACHED, which is correct for this source (early random data). Spell the zero value as the enum name instead of the magic constant. No functional change. Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16983 Notes: svn path=/head/; revision=339491
* Fortuna: trivial static variable cleanupConrad Meyer2018-10-201-1/+1
| | | | | | | | | | | | | Remove unnecessary use of function-local static variable. 32 bytes is small enough to live on the stack. Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16937 Notes: svn path=/head/; revision=339481
* Fortuna: Add trivial assert to match FS&K definitionConrad Meyer2018-10-201-0/+2
| | | | | | | | | | | | | FS&K GenerateBlocks function asserts C (counter) != 0. This should also be true in our implementation. Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16936 Notes: svn path=/head/; revision=339480
* Fortuna: Clean up reseeding key material to closer match FS&KConrad Meyer2018-10-201-1/+2
| | | | | | | | | | | | | | | When reseeding, only incorporate actual key material. Do not include e.g. the derived key schedules or other AES context. I don't think the extra material was harmful here, just not beneficial. Reviewed by: delphij, markm Approved by: secteam (delphij) Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D16934 Notes: svn path=/head/; revision=339479
* random(4): Squash non-error timeout codes from tsleep(9).Xin LI2018-09-091-1/+9
| | | | | | | | | | | | | | | | In both scenarios a timeout (EWOULDBLOCK) is considered as a normal condition and the error should not pop up to upper layers. PR: 231181 Submitted by: cem Reported by: lev Reviewed by: vangyzen, markm, delphij Approved by: re (kib) Approved by: secteam (delphij) Differential Revision: https://reviews.freebsd.org/D17049 Notes: svn path=/head/; revision=338542
* Remove the Yarrow PRNG algorithm option in accordance with due noticeMark Murray2018-08-2611-485/+57
| | | | | | | | | | | | | | | | | | | given in random(4). This includes updating of the relevant man pages, and no-longer-used harvesting parameters. Ensure that the pseudo-unit-test still does something useful, now also with the "other" algorithm instead of Yarrow. PR: 230870 Reviewed by: cem Approved by: so(delphij,gtetlow) Approved by: re(marius) Differential Revision: https://reviews.freebsd.org/D16898 Notes: svn path=/head/; revision=338324
* Limit the amount of "fast" entropy. We don't need nearly as muchMark Murray2018-08-241-1/+9
| | | | | | | | | | | | | | | | for security, and the excess just slows things down badly. PR: 230808 Submitted by: rwmaillists@googlemail.com, but tweeked by me Reported by: Danilo Egea Gondolfo <danilo@FreeBSD.org> Reviewed by: cem,delphij Approved by: re(rgrimes) Approved by: so(delphij) MFC after: 1 Month Differential Revision: https://reviews.freebsd.org/D16873 Notes: svn path=/head/; revision=338293
* Fix braino of mine where the reseeds would happen far too often,Mark Murray2018-08-241-1/+1
| | | | | | | | | | | | | | | | | making the kernel process way too busy. PR: 230808 Submitted by: Conrad Meyer <cem@FreeBSD.org> Reported by: Danilo Egea Gondolfo <danilo@FreeBSD.org> Reviewed by: cem,delphij Approved by: re(rgrimes) Approved by: so(delphij) MFC after: 1 Month Security: Yes Differential Revision: https://reviews.freebsd.org/D16872 Notes: svn path=/head/; revision=338292