📄 rndunix.c
字号:
return( status );
}
/* Unix fast poll - not terribly useful */
#if defined( __hpux ) && ( OSVERSION == 0 || OSVERSION == 9 )
/* PHUX 9.x doesn't support getrusage in libc (wonderful...). The reason we
check for a version 0 as well as 9 is that some PHUX unames report the
version as 09 rather than 9, which looks like version 0 when you take the
first digit */
#include <syscall.h>
static int getrusage( int who, struct rusage *rusage )
{
return( syscall( SYS_getrusage, who, rusage ) );
}
#endif /* __hpux */
/* SCO has a gettimeofday() prototype but no actual system call which
implements it, and no getrusage() at all, so we use times() instead */
#ifdef _M_XENIX
#include <sys/times.h>
#endif /* _M_XENIX */
void fastPoll( void )
{
BYTE buffer[ RANDOM_BUFSIZE ];
int bufIndex = 0;
#ifndef _M_XENIX
struct timeval tv;
struct rusage rusage;
#else
struct tms tms;
#endif /* _M_XENIX */
#ifdef _AIX
timebasestruct_t cpuClockInfo;
#endif /* Aches */
#if ( defined( sun ) && ( OSVERSION >= 5 ) )
hrtime_t hrTime;
#endif /* Slowaris */
/* Mix in the process ID. This doesn't change per process but will
change if the process forks, ensuring that the parent and child data
differs from the parent */
addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, getpid() );
#ifndef _M_XENIX
gettimeofday( &tv, NULL );
addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, tv.tv_sec );
addRandom( buffer, &bufIndex, RANDOM_BUFSIZE, tv.tv_usec );
/* SunOS 5.4 has the function call but no prototypes for it, if you're
compiling this under 5.4 you'll have to copy the header files from 5.5
or something similar */
getrusage( RUSAGE_SELF, &rusage );
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &rusage,
sizeof( struct rusage ) );
#else
times( &tms );
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &tms,
sizeof( struct tms ) );
#endif /* _M_XENIX */
#ifdef _AIX
/* Add the value of the nanosecond-level CPU clock or time base register */
read_real_time( &cpuClockInfo, sizeof( timebasestruct_t ) );
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &cpuClockInfo,
sizeof( timebasestruct_t ) );
#endif /* _AIX */
#if ( defined( sun ) && ( OSVERSION >= 5 ) )
/* Add the value of the nanosecond-level timer */
hrTime = gethrtime();
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &hrTime,
sizeof( hrtime_t ) );
#endif /* Slowaris */
/* Flush any remaining data through */
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, NULL, 0 );
}
/* Slowaris-specific slow poll using kstat, which provides kernel statistics.
Since there can be a hundred or more of these, we use a larger-than-usual
intermediate buffer to cut down on kernel traffic */
#if ( defined( sun ) && ( OSVERSION >= 5 ) )
#define USE_KSTAT
#include <kstat.h>
#define BIG_RANDOM_BUFSIZE ( RANDOM_BUFSIZE * 2 )
static void getKstatData( void )
{
kstat_ctl_t *kc;
kstat_t *ksp;
BYTE buffer[ BIG_RANDOM_BUFSIZE ];
int bufIndex = 0, noEntries = 0;
/* Try and open a kernel stats handle */
if( ( kc = kstat_open() ) == NULL )
return;
/* Walk down the chain of stats reading each one. Since some of the
stats can be rather lengthy, we optionally send them directly to
the randomness pool rather than using the accumulator */
for( ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next )
{
if( kstat_read( kc, ksp, NULL ) == -1 || \
!ksp->ks_data_size )
continue;
addRandomString( buffer, &bufIndex, BIG_RANDOM_BUFSIZE, ksp,
sizeof( kstat_t ) );
if( ksp->ks_data_size > BIG_RANDOM_BUFSIZE )
{
RESOURCE_DATA msgData;
setResourceData( &msgData, ksp->ks_data, ksp->ks_data_size );
krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM );
}
else
addRandomString( buffer, &bufIndex, BIG_RANDOM_BUFSIZE,
ksp->ks_data, ksp->ks_data_size );
noEntries++;
}
kstat_close( kc );
/* Flush any remaining data through and produce an estimate of its
value. We require that we get at least 50 entries and give them a
maximum value of 25 to ensure that some data is still coming from
other sources */
addRandomString( buffer, &bufIndex, BIG_RANDOM_BUFSIZE, NULL, 0 );
if( noEntries > 50 )
{
int quality = 25;
krnlSendMessage( SYSTEM_OBJECT_HANDLE, RESOURCE_IMESSAGE_SETATTRIBUTE,
&quality, CRYPT_IATTRIBUTE_RANDOM_QUALITY );
}
}
#endif /* Slowaris */
/* SYSV /proc interface, which provides assorted information which usually
has to be obtained the hard way via a slow poll */
#if ( defined( sun ) && ( OSVERSION >= 5 ) ) || defined( __osf__ ) || \
defined( __linux__ )
#define USE_PROC
#include <sys/procfs.h>
static void getProcData( void )
{
#ifdef PIOCSTATUS
prstatus_t prStatus;
#endif /* PIOCSTATUS */
#ifdef PIOCPSINFO
prpsinfo_t prMisc;
#endif /* PIOCPSINFO */
#ifdef PIOCUSAGE
prusage_t prUsage;
#endif /* PIOCUSAGE */
BYTE buffer[ RANDOM_BUFSIZE ];
char fileName[ 128 ];
int fd, bufIndex = 0, noEntries = 0;
/* Try and open the process info for this process */
snprintf( fileName, 127, "/proc/%d", getpid() );
if( ( fd = open( fileName, O_RDONLY ) ) == -1 )
return;
/* Get the process status information, misc information, and resource
usage */
#ifdef PIOCSTATUS
if( ioctl( fd, PIOCSTATUS, &prStatus ) != -1 )
{
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &prStatus,
sizeof( prstatus_t ) );
noEntries++;
}
#endif /* PIOCSTATUS */
#ifdef PIOCPSINFO
if( ioctl( fd, PIOCPSINFO, &prMisc ) != -1 )
{
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &prMisc,
sizeof( prpsinfo_t ) );
noEntries++;
}
#endif /* PIOCPSINFO */
#ifdef PIOCUSAGE
if( ioctl( fd, PIOCUSAGE, &prUsage ) != -1 )
{
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, &prUsage,
sizeof( prusage_t ) );
noEntries++;
}
#endif /* PIOCUSAGE */
/* Flush any remaining data through and produce an estimate of its
value. We require that at least two of the sources exist and accesses
succeed and give them a relatively low value since they're returning
information which has some overlap with that returned by the general
slow poll (although there's also a lot of low-level stuff present
which the slow poll doesn't get) */
addRandomString( buffer, &bufIndex, RANDOM_BUFSIZE, NULL, 0 );
if( noEntries >= 2 )
{
int quality = 10;
krnlSendMessage( SYSTEM_OBJECT_HANDLE, RESOURCE_IMESSAGE_SETATTRIBUTE,
&quality, CRYPT_IATTRIBUTE_RANDOM_QUALITY );
}
}
#endif /* Slowaris || OSF/1 || Linux */
/* /dev/random interface */
#define DEVRANDOM_BYTES 128
static void getDevRandomData( void )
{
RESOURCE_DATA msgData;
BYTE buffer[ DEVRANDOM_BYTES ];
static const int quality = 80;
int randFD, noBytes;
/* Check whether there's a /dev/random present. This is somewhat Linux/
x86 BSD-specific, but we try it for all systems in case it's present */
if( ( randFD = open( "/dev/urandom", O_RDONLY ) ) < 0 )
return;
/* Read data from /dev/urandom, which won't block (although the quality
of the noise is less). We only assign this an 80% quality factor to
ensure we still get randomness from other sources as well */
noBytes = read( randFD, buffer, DEVRANDOM_BYTES );
close( randFD );
if( noBytes < 1 )
return;
setResourceData( &msgData, buffer, DEVRANDOM_BYTES );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM );
zeroise( buffer, DEVRANDOM_BYTES );
if( noBytes == DEVRANDOM_BYTES )
krnlSendMessage( SYSTEM_OBJECT_HANDLE, RESOURCE_IMESSAGE_SETATTRIBUTE,
( void * ) &quality, CRYPT_IATTRIBUTE_RANDOM_QUALITY );
}
/* egd/prngd interface */
static void getEGDdata( void )
{
static const char *egdSources[] = {
"/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", NULL };
struct sockaddr_un sockAddr;
RESOURCE_DATA msgData;
BYTE buffer[ DEVRANDOM_BYTES ], *bufPtr = buffer;
static const int quality = 80;
int egdIndex, sockFD, noBytes, status;
/* Look for the egd/prngd output. We re-search each time because,
unlike /dev/random, it's both a user-level process and a movable
feast, so it can disappear and reappear at a different location
between runs */
sockFD = socket( AF_UNIX, SOCK_STREAM, 0 );
if( sockFD < 0 )
return;
for( egdIndex = 0; egdSources[ egdIndex ] != NULL; egdIndex++ )
{
struct sockaddr_un sockAddr;
memset( &sockAddr, 0, sizeof( struct sockaddr_un ) );
sockAddr.sun_family = AF_UNIX;
strcpy( sockAddr.sun_path, egdSources[ egdIndex ] );
if( connect( sockFD, ( struct sockaddr * ) &sockAddr,
sizeof( struct sockaddr_un ) ) >= 0 )
break;
}
if( egdSources[ egdIndex ] == NULL )
{
close( sockFD );
return;
}
/* Read up to 128 bytes of data from the source:
write: BYTE 1 = read data nonblocking
BYTE DEVRANDOM_BYTES = count
read: BYTE returned bytes
BYTE[] data
As with /dev/random we only assign this an 80% quality factor to
ensure we still get randomness from other sources as well */
buffer[ 0 ] = 1;
buffer[ 1 ] = DEVRANDOM_BYTES;
status = write( sockFD, buffer, 2 );
if( status == 2 )
{
status = read( sockFD, buffer, 1 );
noBytes = buffer[ 0 ];
if( status != 1 || noBytes < 0 || noBytes > DEVRANDOM_BYTES )
status = -1;
else
status = read( sockFD, buffer, noBytes );
}
close( sockFD );
if( status != noBytes )
return;
/* Send the data to the pool */
setResourceData( &msgData, buffer, noBytes );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM );
zeroise( buffer, DEVRANDOM_BYTES );
if( noBytes == DEVRANDOM_BYTES )
krnlSendMessage( SYSTEM_OBJECT_HANDLE, RESOURCE_IMESSAGE_SETATTRIBUTE,
( void * ) &quality, CRYPT_IATTRIBUTE_RANDOM_QUALITY );
}
/* Named process information /procfs interface */
static void getProcFSdata( void )
{
static const char *procSources[] = {
"/proc/interrupts", "/proc/loadavg", "/proc/locks", "/proc/meminfo",
"/proc/stat", "/proc/net/tcp", "/proc/net/udp", "/proc/net/dev",
"/proc/net/ipx", NULL };
RESOURCE_DATA msgData;
BYTE buffer[ 1024 ];
static const int quality = 4;
int procIndex, procFD;
/* Read the first 1K of data from some of the more useful sources (most
of these produce far less than 1K output) */
for( procIndex = 0; procSources[ procIndex ] != NULL; procIndex++ )
{
if( ( procFD = open( procSources[ procIndex ], O_RDONLY ) ) >= 0 )
{
const int count = read( procFD, buffer, 1024 );
if( count > 16 )
{
setResourceData( &msgData, buffer, count );
krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM );
krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_SETATTRIBUTE,
( void * ) &quality,
CRYPT_IATTRIBUTE_RANDOM_QUALITY );
}
close( procFD );
}
}
zeroise( buffer, 1024 );
}
/* Unix slow poll. If a few of the randomness sources create a large amount
of output then the slowPoll() stops once the buffer has been filled (but
before all the randomness sources have been sucked dry) so that the
'usefulness' factor remains below the threshold. For this reason the
gatherer buffer has to be fairly sizeable on moderately loaded systems */
#define SHARED_BUFSIZE 49152 /* Usually about 25K are filled */
#define SLOWPOLL_TIMEOUT 30 /* Time out after 30 seconds */
void slowPoll( void )
{
GATHERER_INFO *gathererInfo;
BOOLEAN moreSources;
struct timeval tv;
fd_set fds;
time_t startTime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -