diff --git a/secure_software_development_fundamentals.md b/secure_software_development_fundamentals.md index 0853aeb..326eebb 100644 --- a/secure_software_development_fundamentals.md +++ b/secure_software_development_fundamentals.md @@ -4808,6 +4808,11 @@ Here are some examples of how to call the predictable PRNG versus a cryptographi Random() SecureRandom() + + C (POSIX) + rand(), *rand48() + getentropy() + C# System.Random @@ -4834,9 +4839,7 @@ Another challenge is that software is fundamentally deterministic; given exactly There is a simple solution: use a CSPRNG and use hardware to correctly provide data to it. Most operating system kernels today provide cryptographically secure random numbers by gathering environmental noise from multiple hardware devices and implementing a CSPRNG. If you’re running on bare metal (instead of an operating system kernel) there are usually reusable libraries you can use for this purpose. These cryptographically secure random numbers can be used directly, or can be used as a secure seed for a cryptographically secure PRNG. -For example, the Linux kernel provides cryptographically secure random number values via its `getrandom` system call, as well as the special files `/dev/urandom` and `/dev/random`. In most cases you would want to use the `getrandom` system call where practical, or the `/dev/urandom` special file if `getrandom` is hard to access (e.g., from a shell script). These generate cryptographically secure random values using a CSPRNG and entropy gathered by the kernel. In special circumstances, such as creating a long-lived cryptographic key, you might instead want to use `/dev/random` or the equivalent option in `getrandom`; this forces the kernel to wait (block) until it has a high estimated amount of internal entropy. The purpose of `/dev/random` is to ensure there is a large amount of internal entropy, but the blocking may be indefinite in some circumstances and it’s usually not necessary. What's important is that an attacker can't practically guess the random value, not the value of this internal entropy estimate. (see [“Myths about /dev/urandom”](https://www.2uo.de/myths-about-urandom/) by Thomas). In the future there may be no difference between `/dev/random` and `/dev/urandom`. - -For example, the Linux kernel provides cryptographically secure random number values via its **/dev/urandom** special file, its **/dev/random** special file, and its **getrandom** system call. In most cases you would want to use the **/dev/urandom** special file or the **getrandom** system call. These generate cryptographically secure random values using a CSPRNG and entropy gathered by the kernel. In special circumstances, such as creating a long-lived cryptographic key, you might instead want to use **/dev/random** or the equivalent option in **getrandom**; this forces the kernel to wait (block) until it has a high estimated amount of internal entropy. The purpose of **/dev/random** is to ensure there is internal entropy, but the blocking may be indefinite in some circumstances and it’s usually not necessary +For example, the POSIX specification defines the `getentropy` interface to access a cryptographically secure pseudo-random number generator. On Linux systems `getentropy` is a wrapper around the Linux-specific and more flexible `getrandom` system call. The Linux kernel additionally provides the special readable files `/dev/urandom` and `/dev/random`. The Linux kernel, and many other systems, gather entropy from hardware and mix that into random values using a CSPRNG to provide these cryptographically secure random values. Typical Linux systems record old seeds on shutdown so they will continue to produce highly random values when they reboot. Unfortunately, some of these requests will block - possibly forever - until the underlying system's estimate of internal entropy is high enough (`getentropy`, `/dev/random`, and some uses of `getrandom` will all block). In most cases on Linux kernel based systems you should use avoid blocking indefinitely, and instead use a non-blocking form for `getrandom` or the non-blocking `/dev/urandom`. However, for creating long-lived secrets (like GPG/TLS/SSH keys) where the quality of randomness is especially critical, consider using the blocking versions. This is a potential trade-off between availability and other aspects of security. See the Linux man page [urandom(4)](https://linux.die.net/man/4/urandom). A particularly nasty security problem in computer systems is *insecure random number generators*. An insecure random number generator produces values that look fine, but destroys the security of the entire system. Many failures of cryptographic systems have been traced back to bad random number generation, in part because it can be hard to detect the problem.