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

📄 unix.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
	   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 + -