I recently got around to testing Intel’s Secure Key Digital Random Number Generator (DRNG). Intel Secure Key (code-named Bull Mountain Technology) is the name for the Intel® 64 and IA-32 Architectures instructions RDRAND and RDSEED and the underlying hardware implementation.
The RDRAND and RDSEED instructions address the need for a fast source of entropy. From Intel’s Software Implementation Guide: “The DRNG using the RDRAND instruction is useful for generating high-quality keys for cryptographic protocols, and the RDSEED instruction is provided for seeding software-based pseudorandom number generators (PRNGs).”
Section 2 of the software implementation guide gives an overview of Random Number Generators (RNGs). For another overview of RNGs watch the excellent talk by Melissa O’Neill, or watch my talk. I’ve also found Daniel Lemire’s blog to be an excellent resource on implementing RNGs.
Section 3 of the software implementation guide gives an overview of how Intel’s DRNG works. Thermal noise is the fundamental source of entropy. A hardware CSPRNG (Cryptographically secure PRNG) digital random bit generator feeds the RDRAND instructions over all cores while an ENRNG (Enhanced Non-deterministic Random Number Generator) feeds the RDSEED instructions over all cores. The RDRAND DRNG is continuously reseeded from the hardware entropy source while the RDSEED generator makes conditioned entropy samples directly available.
Determining Support for Intel’s DRNG
Support for RDRAND can be determined by examining bit 30 of the ECX register returned by CPUID, and support for RDSEED can be determined by examining bit 18 of the EBX register.
Using RDRAND and RDSEED
The RDRAND and RDSEED instructions may be called as shown below. The size of the operand register determines whether 16-, 32- or 64-bit random numbers are returned. If the carry flag is zero after a DRNG instruction it means a random number wasn’t available yet and the software should retry if a random number is still required.
Similar to a splitmix64_stateless generator (shown for reference), the rdseed64 generator shown below may be used to seed RNGs:
The assembler for the above rdseed64 generator would look similar to the below snippet. Notice the ‘pause’ instruction which is recommended by Intel so that the core can perhaps still do other work while waiting for a random number.
Below is a Lehmer RNG class (shown for reference) and an Intel 32-bit DRNG class using RDRAND:
In the Intel software implementation guide it is stated that “On real-world systems, a single thread executing RDRAND continuously may see throughputs ranging from 70 to 200 MB/sec, depending on the SPU architecture.”
I also ran some performance measurements on my laptop (which is a 2.9 GHz Intel Core i5 and has cpu_ticks_per_ns = 2.89991):
RDRAND and RDSEED is slower than, for example, the Lehmar generator. However, it provides cryptographically secure hardware entropy based random numbers significantly faster than seems to be otherwise possible.
The full code is available in my Bits-O-Cpp GitHub repo. That code uses some headers for timing and platform info from the repo, but the Bits-O-Cpp/random/README.md file contains info on how to compile the example.