当前位置: 代码迷 >> 综合 >> OpenSSL v0.9.8a随机数发生器分析之三——熵采集
  详细解决方案

OpenSSL v0.9.8a随机数发生器分析之三——熵采集

热度:34   发布时间:2024-01-12 02:00:39.0

4. 熵采集

熵采集函数为RAND_poll,它在不同操作系统下使用不同的熵源产生方式,Windows下的代码.\crypto\rand\rand_win.c

此外,不同的OpenSSL版本中其熵采集方式也有较大出入。

OpenSSL版本

熵采集

v0.9.8a

使用了大量的各种信息,详情见本章后续部分。

v1.1.0

依赖于Windows提供的随机数,不再去采集各种信息。

FIPS版本

使用者自行提供熵,以回调函数方式设置,内部不提供熵。

 

4.1 RAND_poll在Windows下采集熵

作做熵源的信息包括下列信息。

函    数:  int RAND_poll(void)

功能描述:  采集各种熵源添加到内部状态

说    明:  此为Windows版本

注    意:  -

参数说明:  无

返 回 值:  无

执行步骤:下面主要说明添加的各种信息

信息1NetStatisticsGet45字节熵;netstatget17字节熵;

NetStatisticsGet() is a Unicode only function, STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0 contains 17 fields.

NetStatisticsGet(NULL, L"LanmanWorkstation", 0, 0, &outbuf);

RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45);

 

netstatget(NULL, L"LanmanServer", 0, 0, &outbuf);

RAND_add(outbuf, sizeof(STAT_SERVER_0), 17);

 

信息2Windows API 提供的随机数,熵值为sizeof(buf)字节

  1. 2.a如果BCryptGenRandom api存在,则执行,

BCryptGenRandom(NULL, buf, sizeof(buf), flag)

RAND_add(buf, sizeof(buf), sizeof(buf));

这里flag = BCRYPT_USE_SYSTEM_PREFERRED_RNG

  1. 2.b否则,即BCryptGenRandom api不存在,则执行
    1. 2.b.1 windowsCryptGenRandom,熵值为0字节

CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))

CryptGenRandom(hProvider, sizeof(buf), buf);

RAND_add(buf, sizeof(buf), 0);

    1. 2.b.2 intelCryptGenRandom,熵值为sizeof(buf)字节

CryptAcquireContextW(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0))

CryptGenRandom(hProvider, sizeof(buf), buf);

RAND_add(buf, sizeof(buf), sizeof(buf));

信息3windows句柄,熵值为0字节

HWND h = GetForegroundWindow();

RAND_add(&h, sizeof(h), 0);

信息4:鼠标位置,熵值2字节

GetCursorInfo(&ci);

RAND_add(&ci, sizeof(CURSORINFO), 2);

信息5GetQueueStatus状态,熵值1字节

w = GetQueueStatus(QS_ALLEVENTS);

RAND_add(&w, sizeof(w), 1);

信息6:堆信息与遍历,熵值多字节

HEAPLIST32 contains 3 fields that will change with each entry, Consider each field a source of 1 byte of entropy.

HEAPENTRY32 contains 5 fields that will change with each entry, Consider each field a source of 1 byte of entropy.

handle = CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);

hlist.dwSize = sizeof(HEAPLIST32);       

if (good) stoptime = GetTickCount() + MAXDELAY;(为避免时间过长,设置了一个时间阈值)

if (Heap32ListFirst (handle, &hlist)){

      do{

             RAND_add(&hlist, hlist.dwSize, 3);

             hentry.dwSize = sizeof(HEAPENTRY32);

             if (Heap32First(&hentry, hlist.th32ProcessID, hlist.th32HeapID)){

                   int entrycnt = 80;

                   do{

                         RAND_add(&hentry, hentry.dwSize, 5);

                   }while (heap_next(&hentry) && --entrycnt > 0);

             }//end if

      } while (Heap32ListNext(handle, &hlist) && GetTickCount() < stoptime);

}//end if

信息7:进程信息遍历,熵值9字节/进程

PROCESSENTRY32 contains 9 fields that will change with each entry. Consider each field a source of 1 byte of entropy.

p.dwSize = sizeof(PROCESSENTRY32);

if (good) stoptime = GetTickCount() + MAXDELAY;(为避免时间过长,设置了一个时间阈值)

if (Process32First(handle, &p)){

      do

      {

             RAND_add(&p, p.dwSize, 9);

      }while (Process32Next(handle, &p) && GetTickCount() < stoptime);

}//end if

信息8:线程信息遍历,熵值6字节/线程

THREADENTRY32 contains 6 fields that will change with each entry. Consider each field a source of 1 byte of entropy.

t.dwSize = sizeof(THREADENTRY32);

if (good) stoptime = GetTickCount() + MAXDELAY;

if (Thread32First(handle, &t)){

      do{

             RAND_add(&t, t.dwSize, 6);

      }while (Thread32Next(handle, &t) && GetTickCount() < stoptime);

}//end if

信息9:模块遍历,熵值9字节/模块

MODULEENTRY32 contains 9 fields that will change with each entry.  Consider each field a source of  1 byte of entropy.

m.dwSize = sizeof(MODULEENTRY32);

if (good) stoptime = GetTickCount() + MAXDELAY;

if (Module32First(handle, &m)){

      do

      {

             RAND_add(&m, m.dwSize, 9);

      }while (Module32Next(handle, &m) && (GetTickCount() < stoptime));

}//end if

信息10:时间信息,熵值1字节

调用readtimer()获取时间信息加入RAND_add1.1.0版也在用。

1. 优先调用 RDTSC,并增加RAND_add(,,1),即熵加1

2. 上述步骤不可用则调用QueryPerformanceCounter,并增加RAND_add(,,0),即熵加0

3. 上述步骤不可用则调用GetTickCount,并增加RAND_add(,,0),即熵加0

信息11:内存状态信息,熵值1字节

GlobalMemoryStatus Function Retrieves information about the system's current usage of both physical and virtual memory.

GlobalMemoryStatus(&m); /*1.1.0版在用*/

RAND_add(&m, sizeof(m), 1);

信息12:进程ID,熵值1字节

w = GetCurrentProcessId();/*1.1.0版在用*/

RAND_add(&w, sizeof(w), 1);

 

4.2 RAND_poll在unix下采集熵

函数:int RAND_poll(void)

使用系统提供的随机数作为熵源

此外还如下信息

RAND_add (PID,,0);

RAND_add (UID,,0);

RAND_add (time,,0);