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

📄 system.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
CHECK_RETVAL \
static int initCapabilities( void );		/* Fwd.dec for fn.*/

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int initFunction( INOUT DEVICE_INFO *deviceInfo, 
						 STDC_UNUSED const char *name,
						 STDC_UNUSED const int nameLength )
	{
	int status;

	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );

	REQUIRES( name == NULL && nameLength == 0 );

	/* Set up the capability information for this device */
	status = initCapabilities();
	if( cryptStatusError( status ) )
		return( status );

	/* Set up the randomness info */
	status = initRandomInfo( &deviceInfo->randomInfo );
	if( cryptStatusError( status ) )
		return( status );

	/* Complete the initialisation and mark the device as active */
	deviceInfo->label = "cryptlib system device";
	deviceInfo->labelLen = strlen( deviceInfo->label );
	deviceInfo->flags = DEVICE_ACTIVE | DEVICE_LOGGEDIN | DEVICE_TIME;
	return( CRYPT_OK );
	}

STDC_NONNULL_ARG( ( 1 ) ) \
static void shutdownFunction( INOUT DEVICE_INFO *deviceInfo )
	{
	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );

	endRandomInfo( &deviceInfo->randomInfo );
	}

/* Perform a self-test */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int selftestFunction( INOUT DEVICE_INFO *deviceInfo,
							 INOUT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
	{
	CAPABILITY_INFO_LIST **capabilityInfoListPtrPtr = \
		( CAPABILITY_INFO_LIST ** ) &deviceInfo->capabilityInfoList;
	BYTE buffer[ 8 + 8 ];
	int refCount, status;

	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
	assert( isWritePtr( messageExtInfo, \
						sizeof( MESSAGE_FUNCTION_EXTINFO ) ) );

	/* The self-tests need randomness for some of their operations, in order
	   to pre-empt a lack of this from causing a failure somewhere deep down
	   in the crypto code we perform a dummy read of first the randomness 
	   source and then the nonce source to force a full initialisation of 
	   the randomness subsystem */
	status = deviceInfo->getRandomFunction( deviceInfo, buffer, 8, NULL );
	if( cryptStatusError( status ) )
		return( status );
	zeroise( buffer, 8 );
	status = getNonce( deviceInfo->deviceSystem, buffer, 8 );
	if( cryptStatusError( status ) )
		return( status );
	zeroise( buffer, 8 );

	/* Perform an algorithm self-test */
	status = algorithmSelfTest( capabilityInfoListPtrPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Perform the mechanism self-test.  Since this can be quite lengthy and 
	   requires recursive handling of messages by the system object (without
	   actually requiring access to system object state) we unlock it to 
	   avoid it becoming a bottleneck */
	status = krnlSuspendObject( deviceInfo->objectHandle, &refCount );
	if( cryptStatusError( status ) )
		return( status );
	setMessageObjectUnlocked( messageExtInfo );
	return( mechanismSelfTest() );
	}

/* Get random data.  We have to unlock the device around the randomness 
   fetch because background polling threads need to be able to send entropy
   data to it:

				System			Randomness
				------			----------
	getRand ------>|				|
			   [Suspend]			|
				   |--------------->|
				   |				|
				   |<===============| Entropy
				   |<===============| Entropy
				   |<===============| Entropy Quality
				   |				|
				   |<---------------|
			   [Resume]				|
   
   If the caller has specified that it's unlockable and the reference count
   is one or less (meaning that we've been sent the message directly), we 
   leave it unlocked.  Otherwise we re-lock it afterwards. 

   Note that there's a tiny chance of a race condition if the system object 
   is destroyed between the unlock and the acquisition of the randomness 
   mutex (which means that the randomInfo could be freed while we're getting 
   the random data), however there's no easy way around this short of using
   a complex multiple-mutex interlock, and in any case there's only so much 
   that we can do to help a user who pulls data structures out from under 
   active threads */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int getRandomFunction( INOUT DEVICE_INFO *deviceInfo, 
							  OUT_BUFFER_FIXED( length ) void *buffer,
							  IN_LENGTH_SHORT const int length, 
							  INOUT_OPT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
	{
	int refCount, status;

	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
	assert( isWritePtr( buffer, length ) );

	REQUIRES( length > 0 && length < MAX_INTLENGTH_SHORT );

	/* Clear the return value and make sure that we fail the FIPS 140 tests
	   on the output if there's a problem */
	zeroise( buffer, length );

	/* If the system device is already unlocked (which can happen if this 
	   function is called in a loop, for example if multiple chunks of 
	   randomness are read) just return the randomness directly */
	if( messageExtInfo != NULL && isMessageObjectUnlocked( messageExtInfo ) )
		return( getRandomData( deviceInfo->randomInfo, buffer, length ) );

	/* Unlock the system device, get the data, and re-lock it if necessary */
	status = krnlSuspendObject( deviceInfo->objectHandle, &refCount );
	if( cryptStatusError( status ) )
		return( status );
	status = getRandomData( deviceInfo->randomInfo, buffer, length );
	if( messageExtInfo == NULL || refCount > 1 )
		{
		/* The object isn't unlockable or it's been locked recursively, 
		   re-lock it */
		status = krnlResumeObject( SYSTEM_OBJECT_HANDLE, refCount );
		if( cryptStatusError( status ) )
			{
			/* We couldn't re-lock the system object, let the caller know.
			   Since this is a shouldn't-occur condition we also warn the 
			   user in the debug version */
			assert( DEBUG_WARN );
			if( messageExtInfo != NULL )
				setMessageObjectUnlocked( messageExtInfo );
			}
		}
	else
		{
		/* Tell the caller that we've left the object unlocked so they don't
		   have to do anything further with it */
		setMessageObjectUnlocked( messageExtInfo );
		}
	return( status );
	}

/* Handle device control functions */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int controlFunction( INOUT DEVICE_INFO *deviceInfo,
							IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,
							IN_BUFFER_OPT( dataLength ) void *data, 
							IN_LENGTH_SHORT_Z const int dataLength,
							INOUT_OPT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
	{
	int refCount, status;

	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
	assert( data == NULL || isReadPtr( data, dataLength ) );
	
	REQUIRES( type == CRYPT_IATTRIBUTE_ENTROPY || \
			  type == CRYPT_IATTRIBUTE_ENTROPY_QUALITY || \
			  type == CRYPT_IATTRIBUTE_RANDOM_POLL || \
			  type == CRYPT_IATTRIBUTE_RANDOM_NONCE || \
			  type == CRYPT_IATTRIBUTE_TIME );

	/* Handle entropy addition.  Since this can take awhile, we do it with
	   the system object unlocked.  See the comment in getRandomFunction()
	   about the possibility of a race condition */
	if( type == CRYPT_IATTRIBUTE_ENTROPY )
		{
		status = krnlSuspendObject( deviceInfo->objectHandle, &refCount );
		if( cryptStatusError( status ) )
			return( status );
		setMessageObjectUnlocked( messageExtInfo );
		return( addEntropyData( deviceInfo->randomInfo, data, dataLength ) );
		}
	if( type == CRYPT_IATTRIBUTE_ENTROPY_QUALITY )
		{
		status = krnlSuspendObject( deviceInfo->objectHandle, &refCount );
		if( cryptStatusError( status ) )
			return( status );
		setMessageObjectUnlocked( messageExtInfo );
		return( addEntropyQuality( deviceInfo->randomInfo, dataLength ) );
		}
	if( type == CRYPT_IATTRIBUTE_RANDOM_POLL )
		{
		status = krnlSuspendObject( deviceInfo->objectHandle, &refCount );
		if( cryptStatusError( status ) )
			return( status );
		setMessageObjectUnlocked( messageExtInfo );

		/* Perform a slow or fast poll as required */
		if( dataLength == TRUE )
			slowPoll();
		else
			fastPoll();

		return( CRYPT_OK );
		}

	/* Handle nonces */
	if( type == CRYPT_IATTRIBUTE_RANDOM_NONCE )
		return( getNonce( deviceInfo->deviceSystem, data, dataLength ) );

	/* Handle high-reliability time */
	if( type == CRYPT_IATTRIBUTE_TIME )
		{
		time_t *timePtr = ( time_t * ) data;

		*timePtr = getTime();
		return( CRYPT_OK );
		}

	retIntError();
	}

/****************************************************************************
*																			*
*							Device Capability Routines						*
*																			*
****************************************************************************/

/* The cryptlib intrinsic capability list */

#define MAX_NO_CAPABILITIES		32

static const GETCAPABILITY_FUNCTION FAR_BSS getCapabilityTable[] = {
	get3DESCapability,
#ifdef USE_AES
	getAESCapability,
#endif /* USE_AES */
#ifdef USE_BLOWFISH
	getBlowfishCapability,
#endif /* USE_BLOWFISH */
#ifdef USE_CAST
	getCASTCapability,
#endif /* USE_CAST */
	getDESCapability,
#ifdef USE_IDEA
	getIDEACapability,
#endif /* USE_IDEA */
#ifdef USE_RC2
	getRC2Capability,
#endif /* USE_RC2 */
#ifdef USE_RC4
	getRC4Capability,
#endif /* USE_RC4 */
#ifdef USE_RC5
	getRC5Capability,
#endif /* USE_RC5 */
#ifdef USE_SKIPJACK
	getSkipjackCapability,
#endif /* USE_SKIPJACK */

#ifdef USE_MD2
	getMD2Capability,
#endif /* USE_MD2 */
#ifdef USE_MD4
	getMD4Capability,
#endif /* USE_MD4 */
#ifdef USE_MD5
	getMD5Capability,
#endif /* USE_MD5 */
#ifdef USE_RIPEMD160
	getRipemd160Capability,
#endif /* USE_RIPEMD160 */
	getSHA1Capability,
#ifdef USE_SHA2
	getSHA2Capability,
#endif /* USE_SHA2 */

#ifdef USE_HMAC_MD5
	getHmacMD5Capability,
#endif /* USE_HMAC_MD5 */
#ifdef USE_HMAC_RIPEMD160
	getHmacRipemd160Capability,
#endif /* USE_HMAC_RIPEMD160 */
	getHmacSHA1Capability,
#ifdef USE_HMAC_SHA2
	getHmacSHA2Capability,
#endif /* USE_SHA2 */

#ifdef USE_DH
	getDHCapability,
#endif /* USE_DH */
#ifdef USE_DSA
	getDSACapability,
#endif /* USE_DSA */
#ifdef USE_ELGAMAL
	getElgamalCapability,
#endif /* USE_ELGAMAL */
#ifdef USE_RSA
	getRSACapability,
#endif /* USE_RSA */
#ifdef USE_ECC
	getECDSACapability,
#endif /* USE_ECC */

	/* Vendors may want to use their own algorithms, which aren't part of the
	   general cryptlib suite.  The following provides the ability to include
	   vendor-specific algorithm capabilities defined in the file
	   vendalgo.c */
#ifdef USE_VENDOR_ALGOS
	#include "vendalgo.c"
#endif /* USE_VENDOR_ALGOS */

	/* End-of-list marker */
	NULL, NULL
	};

static CAPABILITY_INFO_LIST FAR_BSS capabilityInfoList[ MAX_NO_CAPABILITIES ];

/* Initialise the capability info */

CHECK_RETVAL \
static int initCapabilities( void )
	{
	int i;

	/* Perform a consistency check on the encryption mode values, which
	   are used to index a table of per-mode function pointers */
	assert( CRYPT_MODE_CBC == CRYPT_MODE_ECB + 1 && \
			CRYPT_MODE_CFB == CRYPT_MODE_CBC + 1 && \
			CRYPT_MODE_OFB == CRYPT_MODE_CFB + 1 && \
			CRYPT_MODE_LAST == CRYPT_MODE_OFB + 1 );

	/* Build the list of available capabilities */
	memset( capabilityInfoList, 0,
			sizeof( CAPABILITY_INFO_LIST ) * MAX_NO_CAPABILITIES );
	for( i = 0; 
		 getCapabilityTable[ i ] != NULL && \
			i < FAILSAFE_ARRAYSIZE( getCapabilityTable, GETCAPABILITY_FUNCTION ); 
		 i++ )
		{
		const CAPABILITY_INFO *capabilityInfoPtr = getCapabilityTable[ i ]();

		REQUIRES( sanityCheckCapability( capabilityInfoPtr, FALSE ) );

		capabilityInfoList[ i ].info = capabilityInfoPtr;
		capabilityInfoList[ i ].next = NULL;
		if( i > 0 )
			capabilityInfoList[ i - 1 ].next = &capabilityInfoList[ i ];
		}
	REQUIRES( i < FAILSAFE_ARRAYSIZE( getCapabilityTable, \
									  GETCAPABILITY_FUNCTION ) );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						 	Device Access Routines							*
*																			*
****************************************************************************/

/* Set up the function pointers to the device methods */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int setDeviceSystem( INOUT DEVICE_INFO *deviceInfo )
	{
	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );

	deviceInfo->initFunction = initFunction;
	deviceInfo->shutdownFunction = shutdownFunction;
	deviceInfo->controlFunction = controlFunction;
	deviceInfo->selftestFunction = selftestFunction;
	deviceInfo->getRandomFunction = getRandomFunction;
	deviceInfo->capabilityInfoList = capabilityInfoList;
	deviceInfo->createObjectFunctions = createObjectFunctions;
	deviceInfo->createObjectFunctionCount = \
		FAILSAFE_ARRAYSIZE( createObjectFunctions, CREATEOBJECT_FUNCTION_INFO );
	deviceInfo->mechanismFunctions = mechanismFunctions;
	deviceInfo->mechanismFunctionCount = \
		FAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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