RdRand

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

该随机数生成器要遵守安全标准和加密标准,比如, 和 ANSI X9.82。 和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" 在重新初始化之前,硬件将发出最多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)为回应纽约时报的文章,公开发文表达对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

注脚
参考资料

评论 (0)

  • 还没有评论,来抢沙发吧。