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

📄 lowlvl.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:

			/* Make sure that we can get repeatable results after deleting
			   the hash/MAC and rehashing the data */
			status = cryptDeleteAttribute( cryptContext,
										   CRYPT_CTXINFO_HASHVALUE );
			if( cryptStatusOK( status ) )
				status = cryptDeleteAttribute( decryptContext,
											   CRYPT_CTXINFO_HASHVALUE );
			if( cryptStatusError( status ) )
				{
				printf( "Deletion of hash/MAC value failed with status %d, "
						"line %d.\n", status, __LINE__ );
				destroyContexts( cryptDevice, cryptContext, decryptContext );
				return( FALSE );
				}
			if( cryptStatusError( testCrypt( cryptContext, decryptContext,
											 buffer, isDevice, FALSE ) ) )
				{
				destroyContexts( cryptDevice, cryptContext, decryptContext );
				return( FALSE );
				}
			status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,
											  hash1, &length1 );
			if( cryptStatusError( status ) )
				{
				printf( "Couldn't get hash information for re-hashed data, "
						"status = %d, line %d.\n", status, __LINE__ );
				destroyContexts( cryptDevice, cryptContext, decryptContext );
				return( FALSE );
				}
			if( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )
				{
				puts( "Error: Hash value of re-hashed data differs." );
				destroyContexts( cryptDevice, cryptContext, decryptContext );
				return( FALSE );
				}
			}
		else
			/* If it's a PKC we'll have performed the check during the
			   encrypt/decrypt step */
			if( cryptAlgo < CRYPT_ALGO_FIRST_PKC && \
				!checkTestBuffers( buffer, testBuffer ) )
				{
				destroyContexts( cryptDevice, cryptContext, decryptContext );
				return( FALSE );
				}

		/* Remember that at least one test succeeded */
		testSucceeded = TRUE;
		if( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )
			modesTested[ cryptMode++ ] = TRUE;

		/* Clean up */
		destroyContexts( cryptDevice, cryptContext, decryptContext );
		}
	while( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL && \
		   cryptMode < CRYPT_MODE_LAST );

	/* If it's a conventional algorithm, report the encryption modes that
	   were tested */
	if( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )
		{
		printf( "  Encryption modes tested:" );
		if( modesTested[ CRYPT_MODE_ECB ] )
			printf( " ECB" );
		if( modesTested[ CRYPT_MODE_CBC ] )
			printf( " CBC" );
		if( modesTested[ CRYPT_MODE_CFB ] )
			printf( " CFB" );
		if( modesTested[ CRYPT_MODE_OFB ] )
			printf( " OFB" );
		puts( "." );
		}

	/* Make sure that at least one of the algorithm's modes was tested */
	if( !testSucceeded )
		{
		puts( "No processing modes were found for this algorithm.\n" );
		return( FALSE );
		}

	return( TRUE );
	}

/* Test the ability of the RSA key-load code to reconstruct a full RSA key
   from only the minimal non-CRT components */

int testRSAMinimalKey( void )
	{
	CRYPT_CONTEXT cryptContext, decryptContext;
	BYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];
	int status;

	puts( "Testing ability to recover CRT components for RSA private key..." );

	/* Load the RSA contexts from the minimal (non-CRT) RSA key */
	status = loadRSAContextsEx( CRYPT_UNUSED, &cryptContext, &decryptContext,
								RSA_PUBKEY_LABEL, RSA_PRIVKEY_LABEL, FALSE, 
								TRUE );
	if( !status )
		return( FALSE );

	/* Initialise the test buffers */
	initTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );

	/* Make sure that we can encrypt and decrypt with the reconstituted CRT
	   private key */
	status = testCrypt( cryptContext, decryptContext, buffer, FALSE, FALSE );
	if( cryptStatusError( status ) )
		return( FALSE );

	/* Clean up */
	destroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );

	puts( "RSA CRT component recovery test succeeded." );
	return( TRUE );
	}

/****************************************************************************
*																			*
*								Performance Tests							*
*																			*
****************************************************************************/

/* General performance characteristics test.  Since high-precision timing is
   rather OS-dependent, we only enable this under Windows where we've got
   guaranteed high-res timer access */

#if defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER >= 1100 )

#include <math.h>	/* For sqrt() for standard deviation */

#define NO_TESTS	25

static unsigned long timeDiff( unsigned long startTime )
	{
	unsigned long timeLSB;

#if 1
	LARGE_INTEGER performanceCount;

	/* Sensitive to context switches */
	QueryPerformanceCounter( &performanceCount );
	timeLSB = performanceCount.LowPart;
#else
	FILETIME dummyTime, kernelTime, userTime;
	int status;

	/* Only accurate to 10ms, returns constant values in VC++ debugger */
	GetThreadTimes( GetCurrentThread(), &dummyTime, &dummyTime,
					&kernelTime, &userTime );
	timeLSB = userTime.dwLowDateTime;
#endif /* 0 */

	if( !startTime )
		return( timeLSB );
	if( startTime < timeLSB )
		return( timeLSB - startTime );
	return( ( 0xFFFFFFFF - startTime ) + 1 + timeLSB );
	}

/* Print timing info.  This gets a bit hairy because we're actually counting
   timer ticks rather than thread times, which means we'll be affected by
   things like context switches.  There are two approaches to this:

	1. Take the fastest time, which will be the time least affected by system
	   overhead.

	2. Apply standard statistical techniques to weed out anomalies.  Since
	   this is just for testing purposes all we do is discard any results
	   out by more than 10%, which is crude but reasonably effective.  A
	   more rigorous approach is to discards results more than n standard
	   deviations out, but this gets screwed up by the fact that a single
	   context switch of 20K ticks can throw out results from an execution
	   time of only 50 ticks.  In any case (modulo context switches) the
	   fastest, 10%-out, and 2 SD out times are all within about 1% of each
	   other, so all methods are roughly equally accurate */

static void printTimes( long times[ NO_TESTS + 1 ][ 8 ] )
	{
	int i;

	for( i = 0; i < 7; i++ )
		{
		long timeSum = 0, timeAvg, timeDelta;
		long timeMin = 1000000L, timeCorrSum10 = 0, timeCorrSumSD = 0;
#ifdef USE_SD
		double stdDev;
#endif /* USE_SD */
		int j, timesCount10 = 0, timesCountSD = 0;

		/* Find the mean execution time */
		for( j = 1; j < NO_TESTS + 1; j++ )
			timeSum += times[ j ][ i ];
		timeAvg = timeSum / NO_TESTS;
		timeDelta = timeSum / 10;	/* 10% variation */
		if( timeSum == 0 )
			{
			/* Some ciphers can't provide results for some cases (e.g.
			   AES for 8-byte blocks) */
			printf( "      " );
			continue;
			}

		/* Find the fastest overall time */
		for( j = 1; j < NO_TESTS + 1; j++ )
			if( times[ j ][ i ] < timeMin )
				timeMin = times[ j ][ i ];

		/* Find the mean time, discarding anomalous results more than 10%
		   out */
		for( j = 1; j < NO_TESTS + 1; j++ )
			if( times[ j ][ i ] > timeAvg - timeDelta && \
				times[ j ][ i ] < timeAvg + timeDelta )
				{
				timeCorrSum10 += times[ j ][ i ];
				timesCount10++;
				}
		printf( "%6d", timeCorrSum10 / timesCount10 );
#if 0	/* Print difference to fastest time, usually only around 1% */
		printf( "(%4d)", ( timeCorrSum10 / timesCount10 ) - timeMin );
#endif /* 0 */

#ifdef USE_SD
		/* Find the standard deviation */
		for( j = 1; j < NO_TESTS + 1; j++ )
			{
			const long timeDev = times[ j ][ i ] - timeAvg;

			timeCorrSumSD += ( timeDev * timeDev );
			}
		stdDev = timeCorrSumSD / NO_TESTS;
		stdDev = sqrt( stdDev );

		/* Find the mean time, discarding anomalous results more than two
		   standard deviations out */
		timeCorrSumSD = 0;
		timeDelta = ( long ) stdDev * 2;
		for( j = 1; j < NO_TESTS + 1; j++ )
			if( times[ j ][ i ] > timeAvg - timeDelta && \
				times[ j ][ i ] < timeAvg + timeDelta )
				{
				timeCorrSumSD += times[ j ][ i ];
				timesCountSD++;
				}
		if( timesCountSD == 0 )
			timesCountSD++;	/* Context switch, fudge it */
		printf( "%6d", timeCorrSumSD / timesCountSD );

#if 1	/* Print difference to fastest and mean times, usually only around
		   1% */
		printf( " (dF = %4d, dM = %4d)\n",
				( timeCorrSumSD / timesCountSD ) - timeMin,
				abs( ( timeCorrSumSD / timesCountSD ) - \
					 ( timeCorrSum10 / timesCount10 ) ) );
#endif /* 0 */
#endif /* USE_SD */
		}
	printf( "\n" );
	}

static long encOne( const CRYPT_CONTEXT cryptContext, BYTE *buffer,
					const int length )
	{
	unsigned long timeVal;
	int status;

	memset( buffer, '*', length );
	timeVal = timeDiff( 0 );
	status = cryptEncrypt( cryptContext, buffer, length );
	return( timeDiff( timeVal ) );
	}

static int encTest( const CRYPT_CONTEXT cryptContext,
					const CRYPT_ALGO_TYPE cryptAlgo, BYTE *buffer,
					long times[] )
	{
	int index = 0;

	times[ index++ ] = ( cryptAlgo != CRYPT_ALGO_AES ) ? \
					   encOne( cryptContext, buffer, 8 ) : 0;
	times[ index++ ] = encOne( cryptContext, buffer, 16 );
	times[ index++ ] = encOne( cryptContext, buffer, 64 );
	times[ index++ ] = encOne( cryptContext, buffer, 1024 );
	times[ index++ ] = encOne( cryptContext, buffer, 4096 );
	times[ index++ ] = encOne( cryptContext, buffer, 8192 );
	times[ index++ ] = encOne( cryptContext, buffer, 65536L );
	return( TRUE );
	}

static int encTests( const CRYPT_DEVICE cryptDevice,
					 const CRYPT_ALGO_TYPE cryptAlgo,
					 const CRYPT_ALGO_TYPE cryptMode,
					 BYTE *buffer )
	{
	CRYPT_CONTEXT cryptContext;
	unsigned long times[ NO_TESTS + 1 ][ 8 ], timeVal, timeSum = 0;
	int i, status;

	memset( buffer, 0, 100000L );

	/* Set up the context for use */
	if( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )
		return( FALSE );
	for( i = 0; i < 10; i++ )
		{
		timeVal = timeDiff( 0 );
		status = loadContexts( &cryptContext, NULL, cryptDevice,
							   cryptAlgo, cryptMode,
							   ( BYTE * ) "12345678901234567890",
							   ( cryptAlgo == CRYPT_ALGO_DES ) ? 8 : \
							   ( cryptAlgo == CRYPT_ALGO_3DES || \
							     cryptAlgo == CRYPT_ALGO_RC4 || \
								 cryptAlgo == CRYPT_ALGO_AES ) ? 16 : 0 );
		timeVal = timeDiff( timeVal );
		if( status == CRYPT_ERROR_NOTAVAIL || !status )
			return( FALSE );
		timeSum += timeVal;
		if( i < 9 )
			cryptDestroyContext( cryptContext );
		}
	printf( "Setup time = %d ticks.\n", timeSum / 10 );
	puts( "     8    16    64    1K    4K    8K   64K" );
	puts( "  ----  ----  ----  ----  ----  ----  ----" );

	/* Run the encryption tests NO_TESTS times, discard the first set of
	   results since the cache will be empty at that point */
	for( i = 0; i < NO_TESTS + 1; i++ )
		encTest( cryptContext, cryptAlgo, buffer, times[ i ] );
	printTimes( times );

	/* Re-run the encryption tests with a 1-byte misalignment */
	for( i = 0; i < NO_TESTS + 1; i++ )
		encTest( cryptContext, cryptAlgo, buffer + 1, times[ i ] );
	printTimes( times );

	/* Re-run the encryption tests with a 4-byte misalignment */
	for( i = 0; i < NO_TESTS + 1; i++ )
		encTest( cryptContext, cryptAlgo, buffer + 4, times[ i ] );
	printTimes( times );

	/* Re-run the test 1000 times with various buffer alignments */
	timeVal = 0;
	for( i = 0; i < 1000; i++ )
		timeVal += encOne( cryptContext, buffer, 1024 );
	printf( "Aligned: %d ", timeVal / 1000 );
	timeVal = 0;
	for( i = 0; i < 1000; i++ )
		timeVal += encOne( cryptContext, buffer + 1, 1024 );
	printf( "misaligned + 1: %d ", timeVal / 1000 );
	timeVal = 0;
	for( i = 0; i < 1000; i++ )
		timeVal += encOne( cryptContext, buffer + 4, 1024 );
	printf( "misaligned + 4: %d.\n", timeVal / 1000 );

	return( TRUE );
	}

void performanceTests( const CRYPT_DEVICE cryptDevice )
	{
	LARGE_INTEGER performanceCount;
	BYTE *buffer;

	QueryPerformanceFrequency( &performanceCount );
	printf( "Clock ticks %d times per second.\n", performanceCount.LowPart );
	if( ( buffer = malloc( 100000L ) ) == NULL )
		{
		puts( "Couldn't 100K allocate test buffer." );
		return;
		}
	encTests( CRYPT_UNUSED, CRYPT_ALGO_DES, CRYPT_MODE_ECB, buffer );
	encTests( CRYPT_UNUSED, CRYPT_ALGO_DES, CRYPT_MODE_CBC, buffer );
	encTests( CRYPT_UNUSED, CRYPT_ALGO_3DES, CRYPT_MODE_ECB, buffer );
	encTests( CRYPT_UNUSED, CRYPT_ALGO_3DES, CRYPT_MODE_CBC, buffer );
	encTests( CRYPT_UNUSED, CRYPT_ALGO_RC4, CRYPT_MODE_OFB, buffer );
	encTests( CRYPT_UNUSED, CRYPT_ALGO_AES, CRYPT_MODE_CBC, buffer );
	encTests( CRYPT_UNUSED, CRYPT_ALGO_MD5, CRYPT_MODE_NONE, buffer );
	encTests( CRYPT_UNUSED, CRYPT_ALGO_SHA, CRYPT_MODE_NONE, buffer );
	free( buffer );
	}
#endif /* Win32 with VC++ */

#endif /* TEST_LOWLEVEL || TEST_KEYSET */

⌨️ 快捷键说明

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