RdRand

科技工作者之家 2020-11-17

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。1

RDSEED和RDRAND类似,也提供了访问硬件熵池的高级方法。 Intel Broadwell 系列的CPU和 AMD Zen 系列的CPU都支持RDSEED生成器和rdseed指令。

概览在AMD和Intel的CPU上,CPUID指令都可以检测中央处理器(CPU)是否支持RDRAND指令。如果支持,调用CPUID的标准函数01H之后,EXC寄存器的第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个时钟周期。

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

用来检测RDRAND指令的x86汇编语言例子; 使用 NASM 语法section .datamsg db "0x00000000",10 section .textglobal _start_start:mov eax,1cpuidbt ecx,30mov rdi,1 ; exit code: failurejnc .exit ; 如果没有随机数可用,rdrand 设置 CF=0 ; Intel 的文档建议循环重试10次mov ecx,11.loop1:dec ecxjecxz .exit ; exit code 已经设置了rdrand eaxjnc .loop1 ; 将数字转换成 ASCII 字符mov rdi,msg+9mov ecx,8.loop2:mov edx,eaxand edx,0Fh; add 7 to nibbles of 0xA and above; to align with ASCII code for 'A'; ('A' - '0') - 10 = 7mov r8d,7xor r9d,r9dcmp dl,9cmova r9,r8add edx,r9dadd [rdi],dlshr eax,4dec rdiloop .loop2 mov rax,1 ; SYS_WRITEmov rdi,1 ; stdoutmov rsi,msgmov rdx,11syscall mov rdi,0 ; exit code: success.exit:mov rax,60 ; SYS_EXITsyscall相关背景在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, theSigint Enabling Projecthad 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和威盛电子的代码,并添加说明"对于FreeBSD10,我们将回溯并删除RDRAND和Padlock后端,并将它们提供给Yarrow,而不是将其输出直接传递到 /dev/random 。如果需要,还可以通过内联汇编或使用OpenSSL直接访问硬件随机数生成器,即RDRAND,Padlock等,但是我们不能再信任他们。"

本词条内容贡献者为:

王伟 - 副教授 - 上海交通大学

科技工作者之家

科技工作者之家APP是专注科技人才,知识分享与人才交流的服务平台。