📄 unix.c
字号:
good */
times( &tms );
addRandomData( randomState, &tms, sizeof( struct tms ) );
#endif /* Systems without getrusage() */
#ifdef _AIX
/* Add the value of the nanosecond-level CPU clock or time base register */
read_real_time( &cpuClockInfo, sizeof( timebasestruct_t ) );
addRandomData( randomState, &cpuClockInfo, sizeof( timebasestruct_t ) );
#endif /* _AIX */
#if ( defined( sun ) && ( OSVERSION >= 5 ) )
/* Read the Sparc %tick register (equivalent to the P5 TSC). This is
only readable by the kernel by default, although Solaris 8 and newer
make it readable in user-space. To do this portably, we use
gethrtime(), which does the same thing */
hrTime = gethrtime();
addRandomData( randomState, &hrTime, sizeof( hrtime_t ) );
#endif /* Slowaris */
#if ( defined( __QNX__ ) && OSVERSION >= 5 )
/* Return the output of RDTSC or its equivalent on other systems. We
don't worry about locking the thread to a CPU since we're not using
it for timing (in fact being run on another CPU helps the entropy) */
clockCycles = ClockCycles();
addRandomData( randomState, &clockCycles, sizeof( uint64_t ) );
#endif /* QNX */
/* Flush any remaining data through */
endRandomData( randomState, 0 );
}
/****************************************************************************
* *
* Slow Poll *
* *
****************************************************************************/
/* 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 int getKstatData( void )
{
kstat_ctl_t *kc;
kstat_t *ksp;
RANDOM_STATE randomState;
BYTE buffer[ BIG_RANDOM_BUFSIZE ];
int noEntries = 0, quality;
/* Try and open a kernel stats handle */
if( ( kc = kstat_open() ) == NULL )
return( FALSE );
initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );
/* 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;
addRandomData( randomState, ksp, sizeof( kstat_t ) );
if( ksp->ks_data_size > BIG_RANDOM_BUFSIZE )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, ksp->ks_data, ksp->ks_data_size );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENTROPY );
}
else
addRandomData( randomState, 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 35 to ensure that some data is still coming from
other sources */
quality = ( noEntries > 50 ) ? 35 : 0;
endRandomData( randomState, quality );
return( quality );
}
#endif /* Slowaris */
/* SYSV /proc interface, which provides assorted information that usually
has to be obtained the hard way via a slow poll */
#if ( defined( sun ) && ( OSVERSION >= 5 ) ) || defined( __osf__ ) || \
defined( __alpha__ ) || defined( __linux__ )
#define USE_PROC
#include <sys/procfs.h>
static int getProcData( void )
{
#ifdef PIOCSTATUS
prstatus_t prStatus;
#endif /* PIOCSTATUS */
#ifdef PIOCPSINFO
prpsinfo_t prMisc;
#endif /* PIOCPSINFO */
#ifdef PIOCUSAGE
prusage_t prUsage;
#endif /* PIOCUSAGE */
RANDOM_STATE randomState;
BYTE buffer[ RANDOM_BUFSIZE ];
char fileName[ 128 ];
int fd, noEntries = 0, quality;
/* Try and open the process info for this process */
sPrintf( fileName, "/proc/%d", getpid() );
if( ( fd = open( fileName, O_RDONLY ) ) == -1 )
return;
initRandomData( randomState, buffer, RANDOM_BUFSIZE );
/* Get the process status information, misc information, and resource
usage */
#ifdef PIOCSTATUS
if( ioctl( fd, PIOCSTATUS, &prStatus ) != -1 )
{
#ifdef DEBUG_RANDOM
printf( "rndunix: PIOCSTATUS contributed %d bytes.\n",
sizeof( prstatus_t ) );
#endif /* DEBUG_RANDOM */
addRandomData( randomState, &prStatus, sizeof( prstatus_t ) );
noEntries++;
}
#endif /* PIOCSTATUS */
#ifdef PIOCPSINFO
if( ioctl( fd, PIOCPSINFO, &prMisc ) != -1 )
{
#ifdef DEBUG_RANDOM
printf( "rndunix: PIOCPSINFO contributed %d bytes.\n",
sizeof( prpsinfo_t ) );
#endif /* DEBUG_RANDOM */
addRandomData( randomState, &prMisc, sizeof( prpsinfo_t ) );
noEntries++;
}
#endif /* PIOCPSINFO */
#ifdef PIOCUSAGE
if( ioctl( fd, PIOCUSAGE, &prUsage ) != -1 )
{
#ifdef DEBUG_RANDOM
printf( "rndunix: PIOCUSAGE contributed %d bytes.\n",
sizeof( prusage_t ) );
#endif /* DEBUG_RANDOM */
addRandomData( randomState, &prUsage, sizeof( prusage_t ) );
noEntries++;
}
#endif /* PIOCUSAGE */
close( fd );
/* Flush any remaining data through and produce an estimate of its
value. We require that at least two of the sources exist and accesses
to them succeed, and give them a relatively low value since they're
returning information that has some overlap with that returned by the
general slow poll (although there's also a lot of low-level stuff
present that the slow poll doesn't get) */
quality = ( noEntries > 2 ) ? 10 : 0;
endRandomData( randomState, quality );
return( quality );
}
#endif /* Slowaris || OSF/1 || Linux */
/* /dev/random interface */
#define DEVRANDOM_BYTES 128
static int getDevRandomData( void )
{
RESOURCE_DATA msgData;
BYTE buffer[ DEVRANDOM_BYTES ];
#if defined( __APPLE__ ) || ( defined( __FreeBSD__ ) && OSVERSION == 5 )
static const int quality = 50; /* See comment below */
#else
static const int quality = 75;
#endif /* Mac OS X || FreeBSD 5.x */
int randFD, noBytes;
/* Check whether there's a /dev/random present */
if( ( randFD = open( "/dev/urandom", O_RDONLY ) ) < 0 )
return( 0 );
/* Read data from /dev/urandom, which won't block (although the quality
of the noise is less). We only assign this a 75% quality factor to
ensure that we still get randomness from other sources as well. Under
FreeBSD 5.x and OS X, the /dev/random implementation is broken, using
a pretend dev-random implemented with Yarrow and a 160-bit pool, so
we only assign a 50% quality factor. These generators also lie about
entropy, with both /random and /urandom being the same PRNG-based
implementation */
noBytes = read( randFD, buffer, DEVRANDOM_BYTES );
close( randFD );
if( noBytes < 1 )
return( 0 );
#ifdef DEBUG_RANDOM
printf( "rndunix: /dev/random contributed %d bytes.\n",
DEVRANDOM_BYTES );
#endif /* DEBUG_RANDOM */
setMessageData( &msgData, buffer, DEVRANDOM_BYTES );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ENTROPY );
zeroise( buffer, DEVRANDOM_BYTES );
if( noBytes < DEVRANDOM_BYTES )
return( 0 );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,
( void * ) &quality, CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
return( quality );
}
/* egd/prngd interface */
static int getEGDdata( void )
{
static const char *egdSources[] = {
"/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", NULL };
RESOURCE_DATA msgData;
BYTE buffer[ DEVRANDOM_BYTES ];
static const int quality = 75;
int egdIndex, sockFD, noBytes = CRYPT_ERROR, 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( 0 );
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( 0 );
}
/* 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 a 75% quality factor to
ensure that 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 < 0 ) || ( status != noBytes ) )
return( 0 );
/* Send the data to the pool */
#ifdef DEBUG_RANDOM
printf( "rndunix: EGD (%s) contributed %d bytes.\n",
egdSources[ egdIndex ], DEVRANDOM_BYTES );
#endif /* DEBUG_RANDOM */
setMessageData( &msgData, buffer, noBytes );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ENTROPY );
zeroise( buffer, DEVRANDOM_BYTES );
if( noBytes < DEVRANDOM_BYTES )
return( 0 );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,
( void * ) &quality, CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
return( quality );
}
/* Named process information /procfs interface */
static int getProcFSdata( void )
{
static const char *procSources[] = {
"/proc/interrupts", "/proc/loadavg", "/proc/locks", "/proc/meminfo",
"/proc/net/dev", "/proc/net/ipx", "/proc/net/netstat",
"/proc/net/rt_cache_stat", "/proc/net/snmp",
"/proc/net/softnet_stat", "/proc/net/tcp", "/proc/net/udp",
"/proc/slabinfo", "/proc/stat", "/proc/sys/fs/inode-state",
"/proc/sys/fs/file-nr", "/proc/sys/fs/dentry-state",
"/proc/sysvipc/msg", "/proc/sysvipc/sem", "/proc/sysvipc/shm",
NULL };
RESOURCE_DATA msgData;
BYTE buffer[ 1024 ];
int procIndex, procFD, procCount = 0, quality;
/* 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 )
{
#ifdef DEBUG_RANDOM
printf( "rndunix: %s contributed %d bytes.\n",
procSources[ procIndex ], count );
#endif /* DEBUG_RANDOM */
setMessageData( &msgData, buffer, count );
krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ENTROPY );
procCount++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -