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

📄 random.c

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

		/* Postcondition: The internal state has been copied to the output
		   (ick) */
		FORALL( k, 0, bytesToCopy, \
				data[ dataBlockPos + k ] == randomInfo->x917Pool[ k ] );

		/* V(n+1) = Enc( Enc( DT ) ^ out ); */
		for( i = 0; i < X917_POOLSIZE; i++ )
			randomInfo->x917Pool[ i ] ^= encTime[ i ];
		tdesEncrypt( randomInfo->x917Pool, &randomInfo->x917Key );

		/* If we're using the X9.31 interpretation, update DT to meet the 
		   monotonically increasing time value requirement.  Although the 
		   spec doesn't explicitly state this, the published test vectors
		   increment the rightmost byte, so the value is treated as big-
		   endian */
		if( randomInfo->x917x931 )
			{
			ORIGINAL_INT_VAR( lsb1, randomInfo->x917DT[ X917_POOLSIZE - 1 ] );
			ORIGINAL_INT_VAR( lsb2, randomInfo->x917DT[ X917_POOLSIZE - 2 ] );
			ORIGINAL_INT_VAR( lsb3, randomInfo->x917DT[ X917_POOLSIZE - 3 ] );

#if 1
			for( i = X917_POOLSIZE - 1; i >= 0; i-- )
				{
				randomInfo->x917DT[ i ]++;
				if( randomInfo->x917DT[ i ] != 0 )
					break;
				i = i;
				}
#else
			for( i = 0; i < X917_POOLSIZE; i++ )
				{
				randomInfo->x917DT[ i ]++;
				if( randomInfo->x917DT[ i ] != 0 )
					break;
				i = i;
				}
#endif

			/* Postcondition: The value has been incremented by one */
			POST( ( randomInfo->x917DT[ X917_POOLSIZE - 1 ] == \
					ORIGINAL_VALUE( lsb1 ) + 1 ) || \
				  ( randomInfo->x917DT[ X917_POOLSIZE - 1 ] == 0 && \
					randomInfo->x917DT[ X917_POOLSIZE - 2 ] == \
					ORIGINAL_VALUE( lsb2 ) + 1 ) || \
				  ( randomInfo->x917DT[ X917_POOLSIZE - 1 ] == 0 && \
					randomInfo->x917DT[ X917_POOLSIZE - 2 ] == 0 && \
					randomInfo->x917DT[ X917_POOLSIZE - 3 ] == \
					ORIGINAL_VALUE( lsb3 ) + 1 ) );
			}

		/* Move on to the next block */
		dataPtr += bytesToCopy;
		randomInfo->x917Count++;

		/* Postcondition: We've processed one more block of data */
		POST( dataPtr == data + dataBlockPos + bytesToCopy );
		POST( randomInfo->x917Count == ORIGINAL_VALUE( x917Count ) + 1 );
		}

	/* Postcondition: We processed all of the data */
	POST( dataPtr == data + length );

	zeroise( encTime, X917_POOLSIZE );

	/* Postcondition: Nulla vestigia retrorsum */
	FORALL( i, 0, X917_POOLSIZE,
			encTime[ i ] == 0 );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Add Random (Entropy) Data						*
*																			*
****************************************************************************/

/* Add new entropy data and an entropy quality estimate to the random pool */

int addEntropyData( RANDOM_INFO *randomInfo, const void *buffer, 
					const int length )
	{
	const BYTE *bufPtr = ( BYTE * ) buffer;
	int count = length;
	ORIGINAL_INT_VAR( entropyByteCount, randomInfo->entropyByteCount );
	ORIGINAL_PTR( buffer );

	/* Preconditions: The input data is valid and the current entropy byte 
	   count has a sensible value */
	PRE( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );
	PRE( length > 0 && isReadPtr( buffer, length ) );
	PRE( randomInfo->randomPoolPos >= 0 && \
		 randomInfo->randomPoolPos <= RANDOMPOOL_SIZE );
	PRE( randomInfo->entropyByteCount >= 0 );

	/* Mix the incoming data into the pool.  This operation is resistant to 
	   chosen- and known-input attacks because the pool contents are unknown 
	   to an attacker, so XORing in known data won't help them.  If an 
	   attacker could determine pool contents by observing the generator 
	   output (which is defeated by the postprocessing), we'd have to 
	   perform an extra input mixing operation to defeat these attacks */
	while( count-- > 0 )
		{
		ORIGINAL_INT_VAR( bufVal, *bufPtr );
		DECLARE_ORIGINAL_INT( poolVal );
		DECLARE_ORIGINAL_INT( newPoolVal );
		DECLARE_ORIGINAL_INT( poolPos );

		/* If the pool write position has reached the end of the pool, mix 
		   the pool */
		if( randomInfo->randomPoolPos >= RANDOMPOOL_SIZE )
			mixRandomPool( randomInfo );

		STORE_ORIGINAL_INT( poolVal,
							randomInfo->randomPool[ randomInfo->randomPoolPos ] );
		STORE_ORIGINAL_INT( poolPos, randomInfo->randomPoolPos );

		/* Precondition: We're adding data inside the pool */
		PRE( randomInfo->randomPoolPos >= 0 && \
			 randomInfo->randomPoolPos < RANDOMPOOL_SIZE );

		randomInfo->randomPool[ randomInfo->randomPoolPos++ ] ^= *bufPtr++;

		STORE_ORIGINAL_INT( newPoolVal,
							randomInfo->randomPool[ randomInfo->randomPoolPos - 1 ] );

		/* Postcondition: We've updated the byte at the current pool 
		   position, and the value really was XORed into the pool rather 
		   than (for example) overwriting it as with PGP/xorbytes or 
		   GPG/add_randomness.  Note that in this case we can use a non-XOR 
		   operation to check that the XOR succeeded, unlike the pool mixing 
		   code which requires an XOR to check the original XOR */
		POST( randomInfo->randomPoolPos == \
			  ORIGINAL_VALUE( poolPos ) + 1 );
		POST( ( ( ORIGINAL_VALUE( newPoolVal ) == \
				  ORIGINAL_VALUE( bufVal ) ) && \
				( ORIGINAL_VALUE( poolVal ) == 0 ) ) || \
			  ( ORIGINAL_VALUE( newPoolVal ) != \
			    ORIGINAL_VALUE( bufVal ) ) );
		}

	/* Remember how many bytes of entropy we added on this update */
	randomInfo->entropyByteCount += length;

	/* Postcondition: We processed all of the data */
	POST( bufPtr == ORIGINAL_VALUE( buffer ) + length );
	POST( randomInfo->entropyByteCount == \
		  ORIGINAL_VALUE( entropyByteCount ) + length );

	return( CRYPT_OK );
	}

int addEntropyQuality( RANDOM_INFO *randomInfo, const int quality )
	{
	/* Preconditions: The input data is valid */
	PRE( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );
	PRE( randomInfo->randomQuality >= 0 && \
		 randomInfo->randomQuality < 1000 );

	/* If there's not enough entropy data present to justify the claimed 
	   entropy quality level, signal an error.  We do however retain the
	   existing entropy byte count for use the next time an entropy quality
	   estimate is added, since it's still contributing to the total 
	   entropy quality */
	if( randomInfo->entropyByteCount <= 0 || \
		quality / 2 > randomInfo->entropyByteCount )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_RANDOM );
		}
	randomInfo->entropyByteCount = 0;

	/* If we haven't reached the minimum quality level for generating keys 
	   yet, update the quality level */
	if( randomInfo->randomQuality < 100 )
		randomInfo->randomQuality += quality;
	return( CRYPT_OK );
	}

#ifdef CONFIG_RANDSEED

/* Add entropy data from a stored seed value */

static void addStoredSeedData( RANDOM_INFO *randomInfo )
	{
	STREAM stream;
	BYTE streamBuffer[ STREAM_BUFSIZE ], seedBuffer[ 1024 ];
	char seedFilePath[ MAX_PATH_LENGTH + 128 ];	/* Protection for Windows */
	int poolCount = RANDOMPOOL_SIZE, length, status;

	/* Try and access the stored seed data */
	fileBuildCryptlibPath( seedFilePath, NULL, BUILDPATH_RNDSEEDFILE );
	status = sFileOpen( &stream, seedFilePath, FILE_READ );
	if( cryptStatusError( status ) )
		{
		/* The seed data isn't present, don't try and access it again */
		randomInfo->seedProcessed = TRUE;
		assert( NOTREACHED );
		return;
		}

	/* Read up to 1K of data from the stored seed */
	sioctl( &stream, STREAM_IOCTL_IOBUFFER, streamBuffer, STREAM_BUFSIZE );
	sioctl( &stream, STREAM_IOCTL_PARTIALREAD, NULL, 0 );
	status = length = sread( &stream, seedBuffer, 1024 );
	sFileClose( &stream );
	zeroise( streamBuffer, STREAM_BUFSIZE );
	if( cryptStatusError( status ) || length <= 0 )
		{
		/* The seed data is present but we can't read it, don't try and 
		   access it again */
		randomInfo->seedProcessed = TRUE;
		assert( NOTREACHED );
		return;
		}
	randomInfo->seedSize = length;

	/* Precondition: We got at least some non-zero data */
	EXISTS( i, 0, length, 
			seedBuffer[ i ] != 0 );

	/* Add the seed data to the entropy pool.  Both because the entropy-
	   management code gets suspicious about very small amounts of data with
	   claimed high entropy and because it's a good idea to start with all
	   of the pool set to the seed data (rather than most of it set at zero 
	   if the seed data is short), we add the seed data repeatedly until 
	   we've filled the pool */
	while( poolCount > 0 )
		{
		status = addEntropyData( randomInfo, seedBuffer, length );
		assert( cryptStatusOK( status ) );
		poolCount -= length;
		}

	/* If there were at least 128 bits of entropy present in the seed, set 
	   the entropy quality to the user-provided value */
	if( length >= 16 )
		{
		status = addEntropyQuality( randomInfo, CONFIG_RANDSEED_QUALITY );
		assert( cryptStatusOK( status ) );
		}
	
	zeroise( seedBuffer, 1024 );

	/* Postcondition: Nulla vestigia retrorsum */
	FORALL( i, 0, 1024, 
			seedBuffer[ i ] == 0 );
	}
#endif /* CONFIG_RANDSEED */

/****************************************************************************
*																			*
*								Get Random Data								*
*																			*
****************************************************************************/

/* Get a block of random data from the randomness pool in such a way that
   compromise of the data doesn't compromise the pool, and vice versa.  This
   is done by performing the (one-way) pool mixing operation on the pool and
   on a transformed version of the pool that becomes the key.  The
   transformed version of the pool from which the key data will be drawn is
   then further processed by running each 64-bit block through the X9.17
   generator.  As an additional precaution the key data is folded in half to
   ensure that not even a hashed or encrypted form of the previous contents
   is available.  No pool data ever leaves the pool.

   This function performs a more paranoid version of the FIPS 140 continuous
   tests on both the main pool contents and the X9.17 generator output to
   detect stuck-at faults and short cycles in the output.  In addition the 
   higher-level message handler applies the FIPS 140 statistical tests to 
   the output and will retry the fetch if the output fails the tests.  This 
   additional step is performed at a higher level because it's then applied 
   to all randomness sources used by cryptlib, not just the built-in one.

   Since the pool output is folded to mask the output, the output from each
   round of mixing is only half the pool size, as defined below */

#define RANDOM_OUTPUTSIZE	( RANDOMPOOL_SIZE / 2 )

static int tryGetRandomOutput( RANDOM_INFO *randomInfo,
							   RANDOM_INFO *exportedRandomInfo )
	{
	const BYTE *samplePtr = randomInfo->randomPool;
	const BYTE *x917SamplePtr = exportedRandomInfo->randomPool;
	unsigned long sample;
	int i, status;

	/* Precondition: The pool is ready to do.  This check isn't so much to
	   confirm that this really is the case (it's already been checked
	   elsewhere) but to ensure that the two pool parameters haven't been
	   reversed.  The use of generic pools for all types of random output is
	   useful in terms of providing a nice abstraction, but less useful for
	   type safety */
	PRE( randomInfo->randomQuality >= 100 && \
		 randomInfo->randomPoolMixes >= RANDOMPOOL_MIXES && \
		 randomInfo->x917Inited == TRUE );
	PRE( exportedRandomInfo->randomQuality == 0 && \
		 exportedRandomInfo->randomPoolMixes == 0 && \
		 exportedRandomInfo->x917Inited == FALSE );

	/* Copy the contents of the main pool across to the export pool,
	   transforming it as we go by flipping all of the bits */
	for( i = 0; i < RANDOMPOOL_ALLOCSIZE; i++ )
		exportedRandomInfo->randomPool[ i ] = randomInfo->randomPool[ i ] ^ 0xFF;

	/* Postcondition for the bit-flipping: The two pools differ, and the
	   difference is in the flipped bits */
	POST( memcmp( randomInfo->randomPool, exportedRandomInfo->randomPool,
				  RANDOMPOOL_ALLOCSIZE ) );
	FORALL( i, 0, RANDOMPOOL_ALLOCSIZE, \
			randomInfo->randomPool[ i ] == \
							( exportedRandomInfo->randomPool[ i ] ^ 0xFF ) );

	/* Mix the original and export pools so that neither can be recovered
	   from the other */
	mixRandomPool( randomInfo );
	mixRandomPool( exportedRandomInfo );

	/* Postcondition for the mixing: The two pools differ, and the difference
	   is more than just the bit flipping (this has a 1e-12 chance of a false
	   positive and even that's only in the debug version) */
	POST( memcmp( randomInfo->randomPool, exportedRandomInfo->randomPool,
				  RANDOMPOOL_ALLOCSIZE ) );
	POST( randomInfo->randomPool[ 0 ] != \
			  ( exportedRandomInfo->randomPool[ 0 ] ^ 0xFF ) ||
		  randomInfo->randomPool[ 8 ] != \
			  ( exportedRandomInfo->randomPool[ 8 ] ^ 0xFF ) ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -