(警告:我当然不会声称 HAVEGE 符合其要求。我没有检查过他们的理论或实施。)
为了获得随机性,HAVEGE 和类似系统以“物理事件”为基础,特别是物理事件的时间。此类事件包括硬件中断的发生(反过来,它会收集有关击键、鼠标移动、传入以太网数据包、硬盘完成写入请求的时间......)。HAVEGE 还声称可以提供 CPU 中发生的所有类型的缓存未命中(L1 缓存、L2 缓存、TLB、分支预测......);这些元素的行为取决于 CPU 在之前的几千个时钟周期中所做的事情,因此可能存在一些“随机性”。这取决于能否以极高的精度(不一定准确)测量当前时间,这就是rdtsc
指令开始发挥作用。它返回内部计数器的当前内容,该计数器在每个时钟周期递增,因此它提供亚纳秒精度。
对于虚拟机系统,关于这条指令有三种选择:
- 让指令直接进入硬件。
- 捕获指令并模仿它。
- 完全禁用该指令。
如果 VM 管理器选择第一个解决方案,则rdtsc
具有所有所需的精度,并且应该像在物理机器上一样工作,以便从硬件事件中收集熵。但是,由于这是一个虚拟机,它是宿主系统上的一个应用程序;它不会一直占用 CPU。从使用的客户操作系统的角度来看rdtsc
,这看起来好像它的 CPU 偶尔会被“偷走”:两条连续rdtsc
的指令,名义上相隔一个时钟周期,可能会报告计数器增加数百万。简而言之,当rdtsc
简单地应用于硬件时,客户操作系统可以使用它来检测虚拟机管理程序的存在。
第二种解决方案旨在通过维护一个虚拟的每个 VM 周期计数器来使仿真更加“完美”,该计数器跟踪实际分配给该 VM 的周期。好处是rdtsc
,从客人的角度来看,将不再表现出“被盗周期”效应。缺点是这种模拟是通过触发和捕获 CPU 异常来执行的,从而将rdtsc
操作码的成本从几十个时钟周期(这取决于 CPU 品牌;一些执行rdtsc
不到 10 个周期,其他使用 60 或 70 个周期) ) 超过一千次循环。如果客人尝试做很多事情rdtsc
(就像 HAVEGE 很容易做的那样),然后它会减速到爬行。此外,异常处理代码会破坏措施;代码将测量异常处理程序的执行时间,而不是测量硬件事件时间,这可能会降低提取随机性的质量。
第三种解决方案(禁用rdtsc
)将简单地阻止 HAVEGE 返回良好的随机性。由于它在内部使用了PRNG,因此输出可能仍然会欺骗统计分析工具,因为“看起来随机”和“不可预测”之间存在巨大差异(统计分析工具遵循“看起来随机”路径,但密码安全性依赖于不可预测性)。
VirtualBox 手册声称,默认情况下,VirtualBox 遵循第一种方法(无条件rdtsc
允许并直接应用于硬件),但可以配置为应用第二种解决方案(在这种情况下,您不需要)。
要测试你的虚拟机做了什么,你可以试试这个小程序(gcc -W -Wall -O
在 Linux 上编译;这-O
很重要):
#include <stdio.h>
#if defined(__i386__)
static __inline__ unsigned long long rdtsc(void)
{
unsigned long long int x;
__asm__ __volatile__ (".byte 0x0f, 0x31" : "=A" (x));
return x;
}
#elif defined(__x86_64__)
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
#endif
int
main(void)
{
long i;
unsigned long long d;
d = 0;
for (i = 0; i < 1000000; i ++) {
unsigned long long b, e;
b = rdtsc();
e = rdtsc();
d += e - b;
}
printf("average : %.3f\n", (double)d / 1000000.0);
return 0;
}
在非虚拟机上,使用“true” rdtsc
,这将报告 10 到 100 之间的值,具体取决于 CPU 品牌。如果报告的值为 0,或者程序崩溃,rdtsc
则被禁用。如果值以千为单位,rdtsc
则被模拟,这意味着熵收集可能无法像预期的那样工作。
请注意,即使获得 10 到 100 之间的值也不能保证rdtsc
不被模拟,因为 VM 管理器在维护其虚拟计数器的同时,可能会从中减去执行异常处理程序所需的预期时间。最后,你真的需要好好看看你的虚拟机管理器的手册和配置。
当然,HAVEGE 的整个前提是有问题的。对于任何实际的安全性,您需要一些“真正的随机”位,不超过 200,您将其用作密码安全 PRNG中的种子。PRNG 将产生千兆字节的伪 alea,与真正的随机性无法区分,这对于所有实际目的来说已经足够了。
坚持每一点都回到硬件看起来像是又一次爆发这种有缺陷的想法,将熵视为一种汽油,当你看到它时你会燃烧它。