xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
English Version

NetBSD的OpenSSL PRNG 存在漏洞


发布时间:2001-08-24
更新时间:2001-08-24
严重程度:
威胁程度:其它
错误类型:设计错误
利用方式:服务器模式

受影响系统
NetBSD 1.5.1:
NetBSD 1.5:
pkgsrc: openssl  0.9.6b 或者 0.9.6nb1 之前的版本
详细描述
OpenSSL libcrypto 库包含了PRNG(pseudo random number generator)
实现,不过使用PRNG的逻辑不够强壮,允许攻击者猜测PRNG的内部状态,
因此攻击者可以预测以后PRNG的输出。

测试代码
尚无

解决方案
采用如下补丁crypto/rand/md_rand.c:

--- md_rand.c
+++ md_rand.c
@@ -313,6 +313,7 @@
    {
    static volatile int stirred_pool = 0;
    int i,j,k,st_num,st_idx;
+    int num_ceil;
    int ok;
    long md_c[2];
    unsigned char local_md[MD_DIGEST_LENGTH];
@@ -333,6 +334,12 @@
        }
#endif

+    if (num <= 0)
+        return 1;
+    
+    /* round upwards to multiple of MD_DIGEST_LENGTH/2 */
+    num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2);
+
    /*
     * (Based on the rand(3) manpage:)
     *
@@ -418,11 +425,11 @@
    md_c[1] = md_count[1];
    memcpy(local_md, md, sizeof md);

-    state_index+=num;
+    state_index+=num_ceil;
    if (state_index > state_num)
        state_index %= state_num;

-    /* state[st_idx], ..., state[(st_idx + num - 1) % st_num]
+    /* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num]
     * are now ours (but other threads may use them too) */

    md_count[0] += 1;
@@ -434,6 +441,7 @@

    while (num > 0)
        {
+        /* num_ceil -= MD_DIGEST_LENGTH/2 */
        j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num;
        num-=j;
        MD_Init(&m);
@@ -444,27 +452,28 @@
            curr_pid = 0;
            }
#endif
-        MD_Update(&m,&(local_md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2);
+        MD_Update(&m,local_md,MD_DIGEST_LENGTH);
        MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
#ifndef PURIFY
        MD_Update(&m,buf,j); /* purify complains */
#endif
-        k=(st_idx+j)-st_num;
+        k=(st_idx+MD_DIGEST_LENGTH/2)-st_num;
        if (k > 0)
            {
-            MD_Update(&m,&(state[st_idx]),j-k);
+            MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k);
            MD_Update(&m,&(state[0]),k);
            }
        else
-            MD_Update(&m,&(state[st_idx]),j);
+            MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2);
        MD_Final(local_md,&m);

-        for (i=0; i<j; i++)
+        for (i=0; i<MD_DIGEST_LENGTH/2; i++)
            {
            state[st_idx++]^=local_md[i]; /* may compete with other threads */
-            *(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
            if (st_idx >= st_num)
                st_idx=0;
+            if (i < j)
+                *(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
            }
        }

*** END OF PATCH ***

相关信息