RdRand

RDRAND（之前被称为Bull Mountain）是一个计算机指令，用于从芯片上的硬件随机数生成器中获取随机数。所用到的随机数生成器由芯片上的熵池初始化。 RDRAND指令在架构处理器上可用，该指令也是X86-64和IA-32指令集的一部分。AMD在2015年6月添加了对RdRand指令的支持。

该随机数生成器要遵守安全标准和加密标准，比如， 和 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速率要慢（这两个速率都是所有核心、所有线程共享）https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide  说是 800 megabyte，即 6.4 gigabit每秒。RDSEED用来初始化任意宽度的软件 PRNG，而RDRAND指令适用于需要高质量随机数的应用程序。如果不要求密码学安全，软件随机数生成器比如Xorshift一般会比较快。最简单的64位Xorshift实现具有三次异或和三次逻辑移位；如果这在4核2GHz CPU上运行，吞吐量是80 Gb/s。在实践中，由于存储、加载等开销，吞吐量会减少，但仍然会超过RDRAND的6.4 Gb/s。另一方面，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",10

section .text
global _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）为回应纽约时报的文章，公开发文表达对Linux内核的/dev/random中使用RdRand的担忧：

林纳斯·托瓦兹驳斥了在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等，但是我们不能再信任他们。"

 参见 

 AES指令集
 Bullrun (NSA計畫)
 OpenSSL
 wolfSSL

 注脚 

 参考资料 

Category:机器码
Category:X86微处理器
Category:X86指令
Category:随机数生成