⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rndunix.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -