更多随机性还是更少

来源:互联网 发布:淘宝网的女款衬衣 编辑:程序博客网 时间:2024/06/05 11:52

作者:XiWang

原文地址:http://kqueue.org/blog/2012/06/25/more-randomness-or-less/

CVE-2006-0166一个将未初始化内存用于随机数生成的名声狼藉的例子。一个Debian维护者注掉了两行代码来使Valgrind闭嘴,它抱怨未初始化内存的使用是熵的一个额外来源,这个改变使得OpenSSL在基于Debian的系统上生成伪键值(boguskey)。

事实上,使用未初始化内存总是一个非常坏的主意,不仅因为它迷惑了开发者以及像Valgrind的工具,而且因为一个睿智的C编译器将公然反对你。下面是FreeBSD与Mac OSX libc中的一个例子。

函数srandomdev()用于对random()播种,根据其manpage,“适合密码用途”。它将首先尝试/dev/random,在FreeBSD与Mac OSX上它是非阻塞的;如果失败,它退而求次,以某些令人惊奇的额外比特,使用当前时间与pid。

libc/stdlib/random.clink

struct timeval tv;

unsigned long junk;

 

gettimeofday(&tv, NULL);

srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);

你可以看到使用与未初始化栈变量junk混合的gettimeofday与getpid()的结果来计算种子。下面是来自MacOS X 10.6(SnowLeopard)的对应汇编代码。

/usr/lib/libSystem.B.dylib (10.6)

leaq    0xe0(%rbp),%rdi

xorl    %esi,%esi

callq   0x001422ca      ; symbol stub for: _gettimeofday

callq   0x00142270      ; symbol stub for: _getpid

movq    0xe0(%rbp),%rdx

movl    0xe8(%rbp),%edi

xorl    %edx,%edi

shll    $0x10,%eax

xorl    %eax,%edi

xorl    %ebx,%edi

callq   0x00142d68      ; symbol stub for: _srandom

目前为止一切正常。让我们看一下来自10.7(Lion)与10.8(MountainLion)同样的代码。

/usr/lib/system/libsystem_c.dylib (10.7/10.8)

leaq    0xd8(%rbp),%rdi

xorl    %esi,%esi

callq   0x000a427e      ; symbol stub for: _gettimeofday

callq   0x000a3882      ; symbol stub for: _getpid

callq   0x000a4752      ; symbol stub for: _srandom

等一下,整个种子计算没了!gettimeofday()与getpid()的结果完全没有使用;使用了某些“垃圾”值来调用srandom()。

我猜Apple从GCC转到LLVM来编译新的MacOS X中的libc。因为这个C代码包含未定义行为,未初始化变量junk的使用,LLVM更为进取地优化掉了这个计算。如果使用LLVM编译FreeBSD,你应该看到相同的汇编。下面是几个要探索的有趣的问题。

·        在FreeBSD及Mac OSX上/dev/random以某种方式失败,有可能触发这吗?

·        现在使用LLVM编译的srandom()种子到底有多随机,它只是%edi的值?看起来它是栈变量tv地址的低32比特。

·        GCC会产生“正确的”代码吗?最后的xorl指令使用%ebx,它不太可能对应junk的值,而是/dev/random的文件描述符。

movl    %ebx,%edi

callq   0x00141d48      ; symbol stub for: _close$NOCANCEL

总之,不要因为更多的随机性而使用未初始化的内存。

Junk的使用在1997年引入。Google显示了一组类似的使用与修改。

·        Sranddev()共享相同的后备代码。

·        DragonFly BSD开发者对junk添加了注释“XXXleft uninitialized on purpose”。

·        在2005年,OpenBDS开发者删除了这个代码。

·        Varnish开发者修正了一个类似的使用,虽然这个代码仍然被其他人使用。顺便说一下,在那里你可以找到一个有趣的比较fd>= 0,其中fd是一个指针!

0 0
原创粉丝点击