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

📄 cryptdev.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*						 cryptlib Crypto Device Routines					*
*						Copyright Peter Gutmann 1997-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "crypt.h"
#ifdef INC_ALL
  #include "device.h"
#else
  #include "device/device.h"
#endif /* Compiler-specific includes */

/* When we get random data from a device, we run the (practical) FIPS 140
   tests over the output to make sure that it's really random (at least as 
   far as the tests can tell us).  If the data fails the test, we get more 
   and try again.  The following value defines how many times we retry 
   before giving up.  In test runs, a count of 2 failures is reached every 
   ~50,000 iterations, 5 is never reached (in fact with 1M tests, 3 is never
   reached) */

#define NO_ENTROPY_FAILURES	5

/* Prototypes for functions in crypt.c */

const void FAR_BSS *findCapabilityInfo( const void FAR_BSS *capabilityInfoPtr,
										const CRYPT_ALGO_TYPE cryptAlgo );
void getCapabilityInfo( CRYPT_QUERY_INFO *cryptQueryInfo,
						const void FAR_BSS *capabilityInfoPtr );

/* Prototypes for functions in cryptmis.c */

BOOLEAN checkEntropy( const BYTE *data, const int dataLength );

/****************************************************************************
*																			*
*								Utility Routines							*
*																			*
****************************************************************************/

/* Get a random data block with FIPS 140 checking */

static int getRandomData( DEVICE_INFO *deviceInfoPtr, void *data,
						  const int length )
	{
	int i;

	/* Get random data from the device and check it using the FIPS 140
	   tests.  If it's less than 64 bits we let it pass since the sample
	   size is too small to be useful, samples this small are only ever
	   drawn from the generator for use as padding with crypto keys that
	   are always >= 64 bits, so a problem with the generator will be
	   detected even if we don't check small samples */
	for( i = 0; i < NO_ENTROPY_FAILURES; i++ )
		{
		int status;

		status = deviceInfoPtr->getRandomFunction( deviceInfoPtr, data,
												   length );
		if( cryptStatusOK( status ) && \
			( length < 8 || checkEntropy( data, length ) ) )
			return( CRYPT_OK );
		}

	/* We couldn't get anything that passed the FIPS 140 tests, we can't
	   go any further */
	zeroise( data, length );
	assert( NOTREACHED );
	return( CRYPT_ERROR_RANDOM );
	}

/****************************************************************************
*																			*
*						Device Attribute Handling Functions					*
*																			*
****************************************************************************/

/* Exit after setting extended error information */

static int exitError( DEVICE_INFO *deviceInfoPtr, 
					  const CRYPT_ATTRIBUTE_TYPE errorLocus,
					  const CRYPT_ERRTYPE_TYPE errorType, const int status )
	{
	setErrorInfo( deviceInfoPtr, errorLocus, errorType );
	return( status );
	}

static int exitErrorInited( DEVICE_INFO *deviceInfoPtr, 
							const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	return( exitError( deviceInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT, 
					   CRYPT_ERROR_INITED ) );
	}

static int exitErrorNotFound( DEVICE_INFO *deviceInfoPtr, 
							  const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	return( exitError( deviceInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, 
					   CRYPT_ERROR_NOTFOUND ) );
	}

/* Handle data sent to or read from a device object */

static int processGetAttribute( DEVICE_INFO *deviceInfoPtr,
								void *messageDataPtr, const int messageValue )
	{
	int *valuePtr = ( int * ) messageDataPtr;

	switch( messageValue )
		{
		case CRYPT_ATTRIBUTE_ERRORTYPE:
			*valuePtr = deviceInfoPtr->errorType;
			return( CRYPT_OK );

		case CRYPT_ATTRIBUTE_ERRORLOCUS:
			*valuePtr = deviceInfoPtr->errorLocus;
			return( CRYPT_OK );

		case CRYPT_ATTRIBUTE_INT_ERRORCODE:
			switch( deviceInfoPtr->type )
				{
				case CRYPT_DEVICE_PKCS11:
					*valuePtr = deviceInfoPtr->devicePKCS11->errorCode;
					break;

				case CRYPT_DEVICE_FORTEZZA:
					*valuePtr = deviceInfoPtr->devicePKCS11->errorCode;
					break;

				case CRYPT_DEVICE_CRYPTOAPI:
					*valuePtr = deviceInfoPtr->devicePKCS11->errorCode;
					break;

				default:
					*valuePtr = CRYPT_OK;
				}
			return( CRYPT_OK );

		case CRYPT_DEVINFO_LOGGEDIN:
			if( deviceInfoPtr->flags & DEVICE_REMOVABLE )
				{
				int status;

				/* If it's a removable device, the user could implicitly log
				   out by removing it, so we have to perform an explicit
				   check to see whether it's still there */
				status = deviceInfoPtr->controlFunction( deviceInfoPtr, 
													messageValue, NULL, 0 );
				if( cryptStatusError( status ) )
					return( status );
				}
			*valuePtr = ( deviceInfoPtr->flags & DEVICE_LOGGEDIN ) ? \
						TRUE : FALSE;
			return( CRYPT_OK );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

static int processGetAttributeS( DEVICE_INFO *deviceInfoPtr,
								 void *messageDataPtr, const int messageValue )
	{
	RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;

	switch( messageValue )
		{
		case CRYPT_ATTRIBUTE_INT_ERRORMESSAGE:
			{
			const char *errorMessagePtr;

			switch( deviceInfoPtr->type )
				{
				case CRYPT_DEVICE_PKCS11:
					errorMessagePtr = deviceInfoPtr->devicePKCS11->errorMessage;
					break;

				case CRYPT_DEVICE_FORTEZZA:
					errorMessagePtr = deviceInfoPtr->deviceFortezza->errorMessage;
					break;

				case CRYPT_DEVICE_CRYPTOAPI:
					errorMessagePtr = deviceInfoPtr->deviceCryptoAPI->errorMessage;
					break;

				default:
					errorMessagePtr = "";
				}
			if( !*errorMessagePtr )
				return( exitErrorNotFound( deviceInfoPtr, 
									CRYPT_ATTRIBUTE_INT_ERRORMESSAGE ) );
			return( attributeCopy( msgData, errorMessagePtr,
								   strlen( errorMessagePtr ) ) );
			}

		case CRYPT_DEVINFO_LABEL:
			if( deviceInfoPtr->label == NULL )
				return( exitErrorNotFound( deviceInfoPtr, 
										   CRYPT_DEVINFO_LABEL ) );
			return( attributeCopy( msgData, deviceInfoPtr->label,
								   strlen( deviceInfoPtr->label ) ) );

		case CRYPT_IATTRIBUTE_RANDOM:
			if( deviceInfoPtr->getRandomFunction == NULL )
				return( CRYPT_ERROR_RANDOM );
			return( getRandomData( deviceInfoPtr, msgData->data,
								   msgData->length ) );

		case CRYPT_IATTRIBUTE_RANDOM_NZ:
			{
			BYTE randomBuffer[ 128 ], *outBuffer = msgData->data;
			int count = msgData->length, status = CRYPT_OK;

			if( deviceInfoPtr->getRandomFunction == NULL )
				return( CRYPT_ERROR_RANDOM );

			/* The extraction of data is a little complex because we don't 
			   know how much data we'll need (as a rule of thumb it'll be 
			   size + ( size / 256 ) bytes, but in a worst-case situation we 
			   could need to draw out megabytes of data), so we copy out 128 
			   bytes worth at a time (a typical value for a 1K bit key) and 
			   keep going until we've filled the output requirements */
			while( count > 0 )
				{
				int i;

				/* Copy as much as we can from the randomness pool */
				status = getRandomData( deviceInfoPtr, randomBuffer, 128 );
				if( cryptStatusError( status ) )
					break;
				for( i = 0; count && i < 128; i++ )
					if( randomBuffer[ i ] )
						{
						*outBuffer++ = randomBuffer[ i ];
						count--;
						}
				}
			zeroise( randomBuffer, 128 );
			if( cryptStatusError( status ) )
				zeroise( msgData->data, msgData->length );
			return( status );
			}

		case CRYPT_IATTRIBUTE_RANDOM_NONCE:
			if( deviceInfoPtr->getRandomFunction == NULL )
				return( CRYPT_ERROR_RANDOM );

			assert( deviceInfoPtr->controlFunction != NULL );

			return( deviceInfoPtr->controlFunction( deviceInfoPtr, 
													CRYPT_IATTRIBUTE_RANDOM_NONCE,
													msgData->data, 
													msgData->length ) );

		case CRYPT_IATTRIBUTE_TIME:
			{
			int status;

			/* If the device doesn't contain a time source, we can't provide
			   time information */
			if( !( deviceInfoPtr->flags & DEVICE_TIME ) )
				return( CRYPT_ERROR_NOTAVAIL );

			/* Get the time from the device */
			status = deviceInfoPtr->controlFunction( deviceInfoPtr, 
													 CRYPT_IATTRIBUTE_TIME,
													 msgData->data, 
													 msgData->length );
			if( cryptStatusOK( status ) )
				{
				time_t *timePtr = msgData->data;

				/* Perform a sanity check on the returned value.  If it's
				   too far out, we don't trust it */
				if( *timePtr < MIN_TIME_VALUE )
					{
					*timePtr = 0;
					return( CRYPT_ERROR_NOTAVAIL );
					}
				}

			return( CRYPT_OK );
			}
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

static int processSetAttribute( DEVICE_INFO *deviceInfoPtr,
								void *messageDataPtr, const int messageValue )
	{
	/* If it's an initialisation message, there's nothing to do */
	if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
		return( CRYPT_OK );

	assert( deviceInfoPtr->controlFunction != NULL );

	/* Send the control information to the device */
	return( deviceInfoPtr->controlFunction( deviceInfoPtr, messageValue, NULL, 
											*( ( int * ) messageDataPtr ) ) );
	}

static int processSetAttributeS( DEVICE_INFO *deviceInfoPtr,
								 void *messageDataPtr, const int messageValue )
	{
	const RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
	const BOOLEAN isAuthent = \
			( messageValue == CRYPT_DEVINFO_AUTHENT_USER || \
			  messageValue == CRYPT_DEVINFO_AUTHENT_SUPERVISOR ) ? TRUE : FALSE;
	const BOOLEAN isSetPIN = \
			( messageValue == CRYPT_DEVINFO_SET_AUTHENT_USER || \
			  messageValue == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR ) ? TRUE : FALSE;
	int status;

	assert( deviceInfoPtr->controlFunction != NULL );

	/* If it's a PIN attribute, make sure that a login is actually required 
	   for the device */
	if( isAuthent && !( deviceInfoPtr->flags & DEVICE_NEEDSLOGIN ) )
		return( exitErrorInited( deviceInfoPtr, messageValue ) );

	/* If it's a PIN attribute, make sure that the supplied PIN is valid */
	if( isAuthent || isSetPIN || \
		messageValue == CRYPT_DEVINFO_INITIALISE || \
		messageValue == CRYPT_DEVINFO_ZEROISE )
		switch( deviceInfoPtr->type )
			{
			case CRYPT_DEVICE_PKCS11:

⌨️ 快捷键说明

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