RDRAND和RDSEED CPU功能现在可用

大家好!

我本人不做密码学,但是我的一点研究可能会派上用场。 我决定处理内置的处理器功能RDRAND和RDSEED。 Delphi编译器表示一个未声明的标识符。 嗯 BMI,BMI2,AVX,AVX2甚至AVX-512早已存在,德尔福人定居于SSE4.2。 没关系 我们自己编译代码。

首先,我检查了处理器是否支持这些功能。 当然是CPUID。 您可以从第一个奔腾处理器开始使用CPUID。 我希望没有人考虑在486机器上运行CPUID,因为它尚未出现。 顺便说一句,IvyBridge处理器之前的RDRAND和RDSEED也不存在。

function CPU_support_RDRAND: Boolean; asm mov rax, $01 cpuid test ecx, 40000000h // 30-  setne al end; function CPU_support_RDSEED: Boolean; asm mov rcx, 0 mov rax, $07 // №7 cpuid test ebx, 40000h // 18-  setne al end; 

事实证明,我的Core i7 G6950X Extreme支持这些功能。 因此,我决定手动编译字节码。 对于有经验的人,我会给代码REX和REX.W前缀。 您可能需要将结果写入其他寄存器:

 const REX_RDRAND32: Byte = $F0; //(11b:REG, 110b:OPCODE, 000b:EAX) REX_RDSEED32: Byte = $F8; //(11b:REG, 111b:OPCODE, 000b:EAX) REX_W_RDRAND64: Byte = $48; //(11b:REG, 110b:OPCODE, 000b:RAX) REX_W_RDSEED64: Byte = $48; //(11b:REG, 111b:OPCODE, 000b:RAX) 

功能可以在32位模式和64位模式下工作。 因此,我做到了这两个甚至两个版本。 结果是4个功能:

 function RDRand32: DWord; asm @Retry: db $0F, $C7, $F0 //RDRAND EAX (CF = 1    ) jnc @Retry end; function RDSeed32: DWord; asm @Retry: db $0F, $C7, $F8 //RDSEED EAX (CF = 1    ) jnc @Retry end; function RDRand64: QWord; asm .NOFRAME @Retry: db $48, $0F, $C7, $F0 //RDRAND RAX (CF = 1    ) jnc @Retry end; function RDSeed64: QWord; asm .NOFRAME @Retry: db $48, $0F, $C7, $F8 //RDSEED RAX (CF = 1    ) jnc @Retry end; 

它们的速度比库函数Random的速度慢。 RDRand约为35%,RDSeed为50%或更高,但是生成值的唯一性质量要高得多。 该资源中有关于该主题的好文章,但是我的使命(使功能在Delphi中可用)已经完成。 我没有在拉撒路(Lazarus)中对其进行测试,但是它很可能无需任何更改即可工作。 在函数声明的末尾,您只需要添加备用字汇编器。

这是测试控制台应用程序源代码。 在那里,您可以找到基于内置处理器的Random32和Random64函数的原型。 也许这就是您想要的。 再见!

Source: https://habr.com/ru/post/zh-CN441392/


All Articles