diff --git a/secure_software_development_fundamentals.md b/secure_software_development_fundamentals.md index c4d49fa..c5758ad 100644 --- a/secure_software_development_fundamentals.md +++ b/secure_software_development_fundamentals.md @@ -2475,7 +2475,9 @@ Return codes work, but they have many problems when maintaining software over ti * They lead to functional logic and error handling being mixed together. This often creates more complex code, leading to mistakes and poorer productivity. In particular, such code often fails to deallocate resources if it must do so. -In most programming languages it is often better to use another mechanism (like exception handling) instead, because return codes so easily lead to mistakes over time. This is not practical in portable C, since C does not have many other mechanisms (e.g., C does not have a standard exception handling mechanism). So, if you are using C, consider moving the error handling to the end of the function. This separates error-handling from the functional logic and simplifies correct resource deallocation. A good explanation of this approach is in the [Linux kernel coding style guide](https://www.kernel.org/doc/Documentation/process/coding-style.rst). +In most programming languages it is often better to use another mechanism (like exception handling) instead when you are creating the interface, because return codes so easily lead to mistakes over time. This is not practical in portable C, since C does not have many other mechanisms (e.g., C does not have a standard exception handling mechanism). So, if you are using C, consider moving the error handling to the end of the function. This separates error-handling from the functional logic and simplifies correct resource deallocation. A good explanation of this approach is in the [Linux kernel coding style guide](https://www.kernel.org/doc/Documentation/process/coding-style.rst). + +When you are using an interface that uses return codes, make certain that you check every time there’s a return code if a failure might lead to a vulnerability. For example, about 35 billion Internet of Things (IoT) devices were found in 2021 to have disastrous security vulnerabilities due to inadequate cryptographic random number generation. This is in part because many IoT software developers directly called hardware random number generators (they shouldn’t do that), but even worse, they ignored error return codes from those generators (and they definitely shouldn’t do that). For more details about this example, see [You're Doing IoT RNG](https://labs.bishopfox.com/tech-blog/youre-doing-iot-rng) ([presentation](https://www.youtube.com/watch?v=Zuqw0-jZh9Y)) by Dan Petro and Allan Cecil, a 2021 DEF CON presentation. We’ll discuss cryptographic random number generation in more detail later. #### Exceptions @@ -2895,7 +2897,7 @@ First, if your framework uses session ids in cookies (a common approach), it is 1. The session identifier must have at least 128 bits of random data. -2. The session id must be created using a *cryptographically secure* pseudo-random number generator (PRNG). Anything guessable (like *“add one to the last session id”* or *“ordinary call to random()”)* is not acceptable. We will discuss this in more detail later. +2. The session id must be created using a *cryptographically secure* pseudo-random number generator (CSPRNG). Anything guessable (like *“add one to the last session id”* or *“ordinary call to random()”)* is not acceptable. We will discuss this in more detail later. 3. Encrypt session ids between the web server and web browser. The usual solution is to set the cookie’s **Secure** flag and always communicate using HTTPS (TLS). @@ -3726,7 +3728,7 @@ Threat modeling is overkill if you do not have significant security threats, and # 3. Cryptography -This chapter describes the basics of how to use cryptography to help develop secure software, including the basics of symmetric/shared key encryption algorithms, cryptographic hashes, public-key (asymmetric) encryption, how to securely store passwords, cryptographic pseudo-random number generators (PRNG), and Transport Layer Security (TLS). +This chapter describes the basics of how to use cryptography to help develop secure software, including the basics of symmetric/shared key encryption algorithms, cryptographic hashes, public-key (asymmetric) encryption, how to securely store passwords, cryptographically secure pseudo-random number generators (CSPRNG), and Transport Layer Security (TLS). Learning objectives: @@ -3898,17 +3900,17 @@ As hinted at earlier, it is critical that you use existing well-respected implem [x] Curve25519 is a widely-used algorithm that is generally considered secure. -### Cryptographic Pseudo-Random Number Generator (PRNG) +### Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) Many algorithms depend on secret values that cannot be practically guessed by an attacker. This includes values used by cryptography algorithms (such as nonces), session ids, and many other values. If an attacker can guess a value, including past or future values, many systems become insecure. One challenge is historical: today, the name *random* in programming language libraries usually implies that the function is *not* cryptographically secure. One of the first uses for digital computers was to implement simulations (especially *Monte Carlo simulations*) where random numbers were repeatedly acquired for a simulation. It was often important to be able to *reconstruct* these random numbers so experiments could be repeated. Internally, such random functions would be implemented using algorithms such as a linear congruential generator (LCG), and would often be “seeded” (initialized) by values such as a date/time that can be trivially guessed by an attacker. Because this was one of the first uses of computers, there is a convention across almost all programming languages that the word “random” refers to a way to create a sequence of numbers that could be easily reconstructed later if needed. In other words, the word “random” in programming languages typically implies “*predictably random*”, and that is not what you want in cryptography. Such random numbers *must not* be used for security mechanisms where it is important that an attacker *not* be able to determine the number. -Instead, for almost all security-related tasks you need to use a cryptographically secure PRNG (CSPRNG) for crypto and security-related tasks, as these are not easily predicted. You should *only* use random number generators for security purposes if it says it is a *cryptographic PRNG* - and typically its name will have “secure” and/or “crypto” in it. In their documentation, you may see references to well-accepted cryptographic PRNG algorithms such as Yarrow, Fortuna, ANSI X9.17 (which can use any block cipher), NIST SP 800-90A’s Hash_DRBG, HMAC_DRBG, and CTR_DRBG. +Instead, for cryptography and security-related tasks you need to use a [cryptographically secure pseudo-random number generator (CSPRNG)](https://en.wikipedia.org/wiki/Cryptographically-secure_pseudorandom_number_generator) for crypto and security-related tasks. Put another way, there are many pseudo-random number generator (PRNG) algorithms and implementations, but for security, you should *only* use PRNGs that are cryptographically secure PRNGs (CSPRNGs). A good CSPRNG prevents practically predicting the next output given past outputs (at greater than random chance) and it also prevents revealing past outputs if its internal state is compromised. CSPRNGs are also called cryptographic PRNGs (CPRNGs). Typically a CSPRNG implementation's name will have “secure” and/or “crypto” in it. In their documentation, you may see references to well-accepted CSPRNG algorithms such as Yarrow, Fortuna, ANSI X9.17 (which can use any block cipher), NIST SP 800-90A’s Hash_DRBG, HMAC_DRBG, and CTR_DRBG. **🚩 Never use the algorithm Dual_EC_DRBG, as it is widely accepted that this is a subverted and insecure algorithm.** -Here are some examples of how to call the predictable random number versus a cryptographically secure random number in different programming languages (in practice there are often multiple ways; the point is to show that they are different): +Here are some examples of how to call the predictable PRNG versus a cryptographically secure PRNG in different programming languages (in practice there are often multiple ways; the point is to show that they are different):