**`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",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）为回应*纽约时报*的文章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等，但是我们不能再信任他们。"

参见
--

* 计算机安全主题

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

注脚
--

1. ↑  在一些版本的Ivy Bridge结构处理器上，由于一个bug，RdRand指令会导致一个非法指令异常

参考资料
----

1. ↑  Hofemeier, Gael.. Intel Developer Zone Blogs. 2011-06-22  [December 2013]. （原始内容存档于2017-09-26）.
2. 1 2 3   (PDF). 英特尔. 2012-08-07  [2012-11-25]. （原始内容存档 (PDF)于2013-05-18）.
3. ↑   (PDF). Intel Corporation. January 2013  [2017-09-26]. （原始内容存档 (PDF)于2018-01-01）.
4. ↑   (PDF). AMD Developer Guides, Manuals & ISA Documents. June 2015  [16 October 2015]. （原始内容存档 (PDF)于2017-12-22）.
5. ↑  Barker, Elaine; Kelsey, John.  (PDF). 國家標準技術研究所. January 2012  [September 16, 2013]. （原始内容存档 (PDF)于2013-10-09）.
6. ↑  Jun, Benjamin; Kocher, Paul.  (PDF). Cryptography Research, Inc. 1999-04-22  [2015-08-21]. （原始内容 (PDF)存档于2015-02-13）.
7. ↑  Hamburg, Mike; Kocher, Paul; Marson, Mark.  (PDF). Cryptography Research, Inc. 2012-03-12  [2015-08-21]. （原始内容 (PDF)存档于2014-12-30）.
8. ↑  Hofemeier, Gael.. Intel Developer Zone. Intel. 2012-07-26  [2015-10-24]. （原始内容存档于2015-11-04）.
9. ↑ . www.phoronix.com.  [2015-10-25]. （原始内容存档于2017-03-08）.
10. ↑   (PDF). Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B and 3C. Intel Corporation: 177. June 2013  [24 June 2013]. （原始内容存档 (PDF)于2013-11-04）. All Intel processors that support the RDRAND instruction indicate the availability of the RDRAND instruction via reporting CPUID.01H:ECX.RDRAND[bit 30] = 1
11. ↑   (PDF). AMD: 278. June 2015  [15 October 2015]. （原始内容存档 (PDF)于2017-12-22）. Support for the RDRAND instruction is optional. On processors that support the instruction, CPUID Fn0000\_0001\_ECX[RDRAND] = 1
12. ↑   (PDF). Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B and 3C. Intel Corporation: 177. June 2013  [25 October 2015]. （原始内容存档 (PDF)于2016-08-10）. All Intel processors that support the RDSEED instruction indicate the availability of the RDSEED instruction via reporting CPUID.(EAX=07H, ECX=0H):EBX.RDSEED[bit 18] = 1
13. ↑ . Software.intel.com.  [2014-01-30]. （原始内容存档于2014-01-12）.
14. 1 2  Taylor, Greg; Cox, George.. IEEE Spectrum. September 2011  [2017-10-02]. （原始内容存档于2019-07-01）.
15. ↑  John Mechalas.. software.intel.com. Intel Corporation. November 2012  [1 January 2014]. （原始内容存档于2017-10-02）.
16. ↑  Mechalas, John.. . Intel.  [18 February 2015]. （原始内容存档于2017-10-02）.  外部链接存在于`|website=` (帮助)
17. ↑   （页面存档备份，存于） 说是 800 megabyte，即 6.4 gigabit每秒
18. ↑  最简单的64位Xorshift实现具有三次异或和三次逻辑移位；如果这在4核2GHz CPU上运行，吞吐量是80 Gb/s。在实践中，由于存储、加载等开销，吞吐量会减少，但仍然会超过`RDRAND`的6.4 Gb/s。另一方面，`RDRAND`产生的随机数质量会比软件随机数生成器高，比如Xorshift。
19. ↑   (PDF).  [2017-10-02]. （原始内容 (PDF)存档于2014-07-30）.
20. ↑ .  [2017-10-02]. （原始内容存档于2018-05-20）.
21. ↑ .  [2017-10-02]. （原始内容存档于2017-10-02）.
22. ↑  Ts'o, Theodore.. September 6, 2013  [2017-10-02]. （原始内容存档于2018-06-11）.
23. 1 2  Richard Chirgwin.. The Register. 2013-12-09  [2017-10-02]. （原始内容存档于2017-10-02）.
24. ↑  Gavin Clarke.. theregister.co.uk. 10 September 2013  [12 March 2014]. （原始内容存档于2019-11-09）.
25. ↑  Taylor Hornby.. 6 December 2013  [9 April 2015]. （原始内容存档于2016-03-05）.
26. ↑  
Taylor Hornby [@DefuseSec].  (推文). 10 September 2013  [11 January 2016] –Twitter.
27. ↑  Daniel J. Bernstein; Tanja Lange.  (PDF). 16 May 2014  [9 April 2015]. （原始内容存档 (PDF)于2017-08-25）.
28. ↑ . Freebsd.org.  [2014-01-30]. （原始内容存档于2014-01-22）.