在寻找解决方案以解决虚拟机上的熵池耗尽问题时,我遇到了一个有趣的项目haveged,该项目基于HAVEGE算法(HArdware易失性熵收集和扩展)。



HAVEGE是一个随机数生成器,利用对内部CPU硬件状态(缓存,分支预测变量,TLB)的修改为
/>不确定性的根源。在初始化阶段,处理器的硬件
时钟周期计数器用于收集此熵的一部分:平均每个操作系统调用可以收集成千上万个不可预测的位。


如果这在无头虚拟机上确实产生了几乎无限的高质量熵,则默认情况下应将其包含在每个服务器分发中!然而,有些人提出了担忧。
指令可以虚拟化,并且某些虚拟机主机已选择
禁用此指令,返回0或可预测的结果
。”
(来源:PolarSSL Security Advisory 2011-02 on




此外,流行的NIST和ENT测试有时会给haveged一个PASS,即使它是故意错误配置的,实际上并没有产生随机数!


我用常量0(零)替换了HAVEGE中的“ HARDTICKS”宏,而不是读取处理器的时间戳计数器。这
立即使随机性测试失败。但是,当我改用
常量1(一个)时,ent测试通过了。甚至nist几乎
仅通过了426个执行的测试中的一个未通过的测试就通过了。
那么,哪些虚拟化平台/管理程序可以在虚拟机中与haveged一起安全使用?
是否存在一种公认的最佳实践方法来测试随机源是否产生足够高质量的数字?


评论

尽管某些版本可能已经很老了,但大多数存储库中都包含了hadged。 1.5版引入了AIS31测试。

另请参阅HAVEGE算法中的随机性质量

#1 楼

(注意:我当然不认为HAVEGE符合其要求。我没有检查过它们的理论或实现。)

为了获得随机性,HAVEGE和类似系统以“物理事件”为食,尤其是身体活动的时间安排。这样的事件包括发生硬件中断(依次收集有关按键,鼠标移动,传入的以太网数据包,硬盘完成写请求的时间...)的数据。 HAVEGE还声称可以处理CPU中发生的所有类型的高速缓存未命中(L1高速缓存,L2高速缓存,TLB,分支预测...);这些元素的行为取决于前几千个时钟周期中CPU的状态,因此有可能出现“随机性”。这取决于以高精度(不一定是精度)测量当前时间的可能性,这就是rdtsc指令起作用的地方。它返回内部计数器的当前内容,该内容在每个时钟周期递增,因此提供亚纳秒精度。

对于虚拟机系统,该指令有以下三种选择:


使指令直接进入硬件。
捕获指令并对其进行仿真。
完全禁用指令。

如果VM管理器选择了第一个解决方案,则rdtsc具有所有必需的精度,并且应该与在物理计算机上一样工作,以从硬件事件中收集信息。但是,由于这是虚拟机,因此它是主机系统上的应用程序。它不能一直获取CPU。从使用rdtsc的客户机操作系统的角度来看,它的CPU似乎偶尔被“偷”:标称由单个时钟周期分隔的两个连续的rdtsc指令可能报告计数器增加了几百万。简而言之,当将rdtsc简单地应用在硬件上时,来宾OS便可以使用它来检测虚拟机管理程序的存在。维护每个VM的虚拟周期计数器,该计数器跟踪真正分配给该VM的周期。从访客的角度来看,好处是rdtsc将不再表现出“被盗周期”效应。缺点是此仿真是通过触发和捕获CPU异常来执行的,从几十个时钟周期增加了rdtsc操作码的成本(取决于CPU品牌;有些执行不到10个周期执行rdtsc,其他使用60或70个周期)到一千多个周期。如果访客尝试执行大量rdtsc(因为HAVEGE易于执行),则它将慢下来进行爬网。此外,异常处理代码将破坏该措施。该代码将测量异常处理程序的执行时间,而不是测量硬件事件计时,这可能会降低提取的随机性的质量。

第三种解决方案(禁用rdtsc)将仅阻止HAVEGE返回良好的随机性。由于它内部使用PRNG,因此输出可能仍然愚弄统计分析工具,因为“看起来随机”和“变得不可预测”之间存在巨大差异(统计分析工具遵循“看起来随机”的路径,但是密码安全性依赖于不可预测性) )。

VirtualBox手册声称VirtualBox在默认情况下遵循第一种方法(无条件允许rdtsc并直接在硬件上应用),但可以配置为应用第二种解决方案(您不这样做)在这种情况下是不需要的。

要测试您的VM的功能,可以尝试使用此小程序(在Linux上使用gcc -W -Wall -O进行编译; -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管理器在维持其虚拟计数器的同时,可能会从中减去执行异常处理程序所需的预期时间。最终,您确实需要仔细了解VM管理器的手册和配置。


当然,HAVEGE的整个前提是有问题的。对于任何实际的安全性,您需要不超过200个“真实随机”位,并将其用作加密安全PRNG中的种子。 PRNG将产生与真正的随机性无法区分的千兆字节的假丙二醛,对于所有实际目的而言已经足够了。

坚持不懈地回到硬件上似乎又是这个有缺陷想法的爆发,该想法将熵视为一种汽油,当您看着它时就会燃烧。

评论


伪造的最新版本使用AIS31(德国通用标准组织用来验证智能卡的测试套件)对输出进行运行时测试,请访问issihosts.com/haveged/ais31.html并设置一个恒定值在高分辨率计时器中,黑洞的行为可能类似于长序列prng(或者不取决于位模式的细节)。如果输出通过了连续测试,那有什么关系?如果有的话,那就表明定时器源的细节并不像人们想象的那么重要。

– gwuertz
13年4月18日在21:37



@gwuertz:即使输出的熵源已固定(根本没有任何度量!),如果输出仍通过连续测试,则这意味着测试不足以测试密码强度,这是预期的,因为此类测试是用于统计模式,而不是用于不可预测性。如果您使用强加密级别的PRNG并将其固定为0,则您还将成功通过所有此类测试,但是您的安全性将为零。

–汤姆韭菜
13年4月18日在23:00

我还可以补充一点,我对信任人们实施PRNG表示保留,这是因为他们表明他们测试结果的框架是统计测试,从定义上说,这对于密码使用来说是可怕的。这不是一个好兆头。

–汤姆韭菜
13年4月18日在23:02

@TomLeek有替代方法吗?我一直以为本身没有可预测性的证据。

–aef
2014年5月22日18:11

密码学家使用详尽而透彻的同行评审来确保他们的设计显然不错。现在那不是很好。我的观点是,统计测试在评估安全性方面很糟糕。这样的测试只能检测到极差和较弱的PRNG。使PRNG通过所有此类测试很容易(嘿,即使是LFSR也可以做到)。从密码学家的角度来看,它甚至不值得报告。打个比方:一家汽车制造商看起来像在发布大型广告,声称自己的汽车很棒,因为他已经核实了它们的车轮。

–汤姆韭菜
2014年5月22日在22:19

#2 楼

关于Polarssl咨询:可在最新的debian资料中找到详细的技术回复:

http://bazaar.launchpad.net/~ubuntu-branches/debian/experimental/haveged/experimental/修订版/12?start_revid=12#debian/README.Debian

执行摘要是:polarssl!=冒充!= HAVEGE

在embloms.se模拟器上进行实验: br />
haveged测试套件NISTent验证源代码版本已生成功能正常的RNG。需要运行时测试来验证虚拟环境中的紧急操作。

统计测试:

假设您有一个hardware RNGTRNG,您怎么知道它没有坏?硬件中断。德国标准机构有一个可以解决这个问题的规范AIS31。避风港采用了这种方法。应用于RNG的RNG标准的(有偏见的)讨论可以在以下位置找到:

http://www.issihosts.com/haveged/ais31.html

HAVEGE的不可预测性与基准测试软件中的机制完全相同。这不是由于计时器漂移,而是由于现代处理器中异步行为的聚集。性能变化是来自缓存未命中还是传递给另一个处理器的时间片,这真的不重要。只要“足够”,计时器的精度也无关紧要。如何确定的?由输出。通过设计(或者可能是过度设计),/dev/random可以不受不良输入数据的影响。颠覆设计的唯一方法是依靠添加到熵池中的熵。最新版本的Haveged对生成的输出执行运行时熵估计,以确保输出与理想的TRNG一致。

内容提要:根据德国标准机构用于认证haveged的测试,TRNG的输出与TRNG是无法区分的。如果不是这种情况,haveged将关闭。

#3 楼

(已更新,多亏了haveged的当前作者/维护者gwuertz,我错过了HAVEGEhaveged之间的分隔。) ,维护和文档记录在这里:http://www.issihosts.com/haveged/(不再直接使用libhavege)。

haveged并不是很新(2006年),尽管有人对其进行了修补最近(2009年)的速度和正确性。我会保持谨慎,因为它没有记录其方法,没有提及虚拟机,并且如上所述,(大量)依赖于HAVEGE(或等同于平台)。 (同样,源代码让我不寒而栗,但这是很主观的。)

我认为主机VM不应无意间将任何状态泄漏给guest虚拟机,因此不应将其视为良好的源代码。

在Linux上,更好的方法是带有virtio-rng超虚拟化rng驱动程序的rng-tools(即,允许来宾访问主机收集的熵,从而消除了许多有关访客查看“随机”事件),或者您可能会发现Entropy Broker更有用。在最近的Intel芯片上,您还可以向来宾公开RDRAND指令,以避开此问题。

这篇文章(摘自hpa在LinuxCon Europe 2012上的演讲)非常有用,请阅读:http://lwn.net / Articles / 525459 /,还讨论了RDTSC / HAVEGE(尽管两者之间的区别也不清楚)。统计信息可以用来识别伪随机数据吗?

评论


最新的隔离版本是2013年2月。请尝试freecode.com或上游(me),在旧的Polarssl脆弱性上:bazaar.launchpad.net/~ubuntu-branches/debian/experimental / ...

– gwuertz
13年4月18日在21:37



我不知道,源代码在客观上似乎很糟糕。有时if(cond),有时if(cond),有时if(cond)?有时是双缩进,有时是三重,有时是四重?有时a == b,有时a == b,有时a == b?从字面上令人恐惧。如果有任何注释,则每个注释中可能会有三个错别字(咳嗽imlib2咳嗽)。

–森林
18-3-17在5:05