Project 3.11 Section 3 ⚡ Embedded Relevance: High PRNG TRNG Hardware RNG Entropy Cryptography

3.11 std::rand() Hazards, Seed Management & Hardware True Random Number Generators (TRNG)

Executive Summary: Exploring random number generation and dice simulation. We analyze the severe cryptographic and statistical flaws of std::rand() (Linear Congruential Generators), seed initialization from uninitialized ADC noise, and hardware True Random Number Generators (TRNG peripherals) on microcontrollers (e.g. STM32 RNG).

💻 1. Annotated Source Code

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main() {

	srand(time(nullptr));

	int dieValue;

	for (int i = 0; i < 10; i++) {
		dieValue = rand() % 6 + 1;
		cout << "Roll " << (i + 1) << ": " << dieValue << endl;
	}

	return 0;
}

📐 2. Architecture & UML Class Model

📐 Die Rolling State Machine & Pseudo-Random Model
+ Public - Private # Protected
<<struct>> DieSimulator Die State
+sides : uint8_t = 6
+lastRoll : uint8_t
+roll() : uint8_t

📚 3. Core C++ Concepts Deep-Dive

1. Pseudo-Random Number Generators (PRNG)

Standard std::rand() is a Linear Congruential Generator (LCG). Given the same initial seed (std::srand(seed)), it produces the exact same deterministic sequence of numbers.

2. Modulo Bias

Computing rand() % 6 introduces Modulo Bias: lower numbers have a slightly higher probability of being chosen because RAND_MAX is rarely an exact multiple of 6.

⚡ 4. Embedded Systems & Hardware Reality

1. Microcontroller Hardware True RNG (TRNG)

Modern microcontrollers (such as STM32, ESP32, nRF52) feature dedicated on-chip Hardware TRNG peripherals. They harvest physical analog thermal noise from ring oscillators to produce 100% non-deterministic cryptographic entropy for AES keys, BLE pairing, and secure boot.

💡 5. Production-Ready Embedded Refactoring

Hardware True Random Number Generator (TRNG) driver:

💡 Production-Ready Refactor
#include <cstdint>

// Hardware TRNG Peripheral Access (STM32 RNG)
struct HardwareRNG {
    volatile uint32_t CR;  // Control Register
    volatile uint32_t SR;  // Status Register
    volatile uint32_t DR;  // Data Register (32-bit random word)
};

uint32_t getHardwareTrueRandom() noexcept {
    HardwareRNG* const rng = reinterpret_cast<HardwareRNG*>(0x50060800);
    while ((rng->SR & 1UL) == 0); // Wait for Data Ready (DRDY)
    return rng->DR; // True physical analog entropy!
}

📝 Knowledge Verification Quiz

Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.

Q1. Why is 'std::rand()' strictly prohibited for cryptographic keys, BLE pairing, or secure IoT boot?
A It is a deterministic Linear Congruential Generator with short cycles; observing a few outputs allows attackers to predict all future keys
B It runs too slowly
C It consumes 100KB of RAM
D It can only generate negative numbers
Detailed Explanation: std::rand() is mathematically predictable and not cryptographically secure; attackers can reverse-engineer internal state from a few samples.
Q2. What physical phenomenon do on-chip hardware True Random Number Generators (TRNG) sample to generate entropy?
A Analog thermal noise, transistor shot noise, and jitter from internal analog ring oscillators
B The CPU crystal frequency
C The number of lines of code
D The ambient room temperature in Celsius
Detailed Explanation: Hardware TRNGs sample physical analog thermal noise across multiple asynchronous ring oscillators to produce true non-deterministic entropy.
Q3. What is 'Modulo Bias' when scaling random numbers (e.g. rand() % 6)?
A A statistical distortion where numbers below the remainder of RAND_MAX % 6 occur with higher probability than numbers above it
B A compiler error caused by division
C A memory leak on the heap
D A hardware fault on ARM
Detailed Explanation: When the generator range is not an exact multiple of the target range, smaller outcomes receive one extra value in the mapping, skewing fairness.
Q4. How do developers without a hardware TRNG seed a PRNG on basic microcontrollers?
A Sample the least significant bits of an unconnected, floating analog ADC pin to capture ambient electromagnetic noise
B Hardcode the seed to 0
C Use the compiler version number
D Use the baud rate
Detailed Explanation: Reading a floating ADC pin captures ambient atmospheric electromagnetic noise, providing an initial random seed for PRNG algorithms.