RdRand

RDRAND（之前被称为Bull Mountain）是一个计算机指令，用于从芯片上的硬件随机数生成器中获取随机数。所用到的随机数生成器由芯片上的熵池初始化。 RDRAND指令在Ivy Bridge架构处理器上可用，该指令也是X86-64和IA-32指令集的一部分。AMD在2015年6月添加了对RdRand指令的支持。
该随机数生成器要遵守安全标准和加密标准，比如NIST SP 800-90A， FIPS 140-2和 ANSI X9.82。 Intel也在1999年和2012年请密码学研究Cryptography Research 公司来审查这个随机数发生器，并产生了两篇论文：1999年的The Intel Random Number Generator 和2012年的Analysis of Intel's Ivy Bridge Digital Random Number Generator。
RDSEED和RDRAND类似，也提供了访问硬件熵池的高级方法。
Intel Broadwell 系列的CPU 和 AMD Zen 系列的CPU都支持RDSEED生成器和rdseed指令。

概览

在AMD和Intel的CPU上，CPUID指令都可以检测中央处理器（CPU）是否支持RDRAND 指令。如果支持，调用CPUID的标准函数01H之后，ECX寄存器的第30位会被设置成1。AMD处理器也可以使用同样的方式检测是否支持。在Intel CPU上，也可以使用类似的方法检测RDSEED是否支持。如果支持RDSEED，在调用完CPUID的标准函数07H后，EBX寄存器的第18位会被设置为1。
RDRAND的操作码是0x0F 0xC7，后面跟一个ModRM字节，来指示目标寄存器。在64位模式下，还可以于REX前缀结合（这是可选的）。
Intel安全密钥是Intel为RDRAND指令和底层的随机数生成器（RNG）的硬件实现的统称，它在开发期间的代号是"Bull Mountain"。Intel称自己的RNG"数字随机数生成器"或DRNG。生成器采用有硬件产生的256位原始熵样本对，并将其应用到一个高级加密标准（AES）（在CBC-MAC模式下）调节器，将其减少到256位条件熵样本。
NIST SP 800-90A中定义了一个名叫CTR_DRBG的确定性随机数生成器。它由调节器的输出来初始化，为使用RDRAND指令的应用程序提供了密码学安全的随机数。 在重新初始化之前，硬件将发出最多511个128位的样本。使用RDSEED可以访问来自AES-CBC-MAC的、条件化后的256位样本。

为了初始化另一个为随机数生成器，RDSEED指令被添加到了Intel安全密钥，在Broadwell微架构的CPU上开始支持。RDSEED指令的熵来源自时序线路，并且使用硅片上的热噪声来以3GHz的速度输出随机比特流。这比从RDRAND获得的6.4Gbit/s速率要慢（这两个速率都是所有核心、所有线程共享）。RDSEED用来初始化任意宽度的软件PRNG，而RDRAND指令适用于需要高质量随机数的应用程序。如果不要求密码学安全，软件随机数生成器比如Xorshift一般会比较快。

性能

在Intel 酷睿 i7-7700K，4500MHz（45 x 100MHz）的处理器（Kaby Lake-S架构）上，单个RDRAND或RDSEED指令花费110纳秒或463个时钟周期，不论操作数大小（16位、32位、64位）。这个时钟周期数适用于所有Skylake和Kaby Lake架构的处理器。在Silvermont架构的处理器上，每个指令花费1472时钟周期，不论操作数大小；在Ivy Bridge架构的处理器上，花费117时钟周期。
在AMD Ryzen 处理器上，对于16位或32位操作数，每个指令约花费1200个时钟周期；对于64位操作数，约花费2500个时钟周期。

编译器支持

GCC 4.6+和Clang 3.2+提供了RdRand的内置支持——当在编译参数中指定了-mrdrnd命令行参数、并且在条件编译时设置__RDRND__宏的情况下。更新的版本额外提供了immintrin.h将这些内置函数封装成与英特尔C编译器版本12.1+兼容的功能中。这些函数将随机数据写入参数指定的位置，并在成功时返回1 。

用来检测RDRAND指令的x86汇编语言例子

; 使用 NASM 语法section .data
msg db "0x00000000",10section .textglobal _start_start:
mov eax,1
cpuid
bt ecx,30
mov rdi,1 ; exit code: failure
jnc .exit

; 如果没有随机数可用，rdrand 设置 CF=0
        ; Intel 的文档建议循环重试10次
mov ecx,11.loop1:
dec ecx
jecxz .exit ; exit code 已经设置了
rdrand eax
jnc .loop1

; 将数字转换成ASCII 字符
mov rdi,msg+9
mov ecx,8.loop2:
mov edx,eax
and edx,0Fh
; add 7 to nibbles of 0xA and above
; to align with ASCII code for 'A'
; ('A' - '0') - 10 = 7
mov r8d,7
xor r9d,r9d
cmp dl,9
cmova r9,r8
add edx,r9d
add [rdi],dl
shr eax,4
dec rdi
loop .loop2

mov rax,1 ; SYS_WRITE
mov rdi,1 ; stdout
mov rsi,msg
mov rdx,11
syscall

mov rdi,0 ; exit code: success.exit:
mov rax,60 ; SYS_EXIT
syscall

Reception

在2013年9月，曹子德（Theodore Ts'o）为回应纽约时报的文章Global surveillance disclosures (2013–present)，公开发文表达对Linux内核的/dev/random中使用RdRand的担忧：
I am so glad I resisted pressure from Intel engineers to let /dev/random rely only on the RDRAND instruction. To quote from the article below: 'By this year, the Sigint Enabling Project had found ways inside some of the encryption chips that scramble information for businesses and governments, either by working with chipmakers to insert back doors....' Relying solely on the hardware random number generator which is using an implementation sealed inside a chip which is impossible to audit is a BAD idea.
林纳斯·托瓦兹驳斥了在Linux内核中使用RdRand的担忧，并指出RdRand不是/dev/random的唯一熵来源；从RdRand接受数据并和其他随机数来源结合来改善熵。 然而，Defuse Security的Taylor Hornby表明，如果将后门引入到专门针对使用代码的RdRand指令中，Linux随机数生成器可能会变得不安全。 泰勒的概念验证实现在版本3.13之前的未修改的Linux内核上工作。
开发者注释掉了FreeBSD内核中直接使用RdRand和威盛电子的代码，并添加说明"对于 FreeBSD 10，我们将回溯并删除RDRAND和Padlock后端，并将它们提供给Yarrow，而不是将其输出直接传递到/dev/random 。如果需要，还可以通过内联汇编或使用OpenSSL直接访问硬件随机数生成器，即RDRAND，Padlock等，但是我们不能再信任他们。"