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

📄 cryptdev.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						 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 "misc/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 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

/* Some device types aren't supported on some platforms, so we replace a
   call to the mapping function with an error code */

#ifndef __WINDOWS__
  #define setDeviceFortezza( x )		CRYPT_ARGERROR_NUM1
#endif /* !__WINDOWS__ */
#ifndef DEV_PKCS11
  #define setDevicePKCS11( x, y, z )	CRYPT_ARGERROR_NUM1
#endif /* !DEV_PKCS11 */

/* Prototypes for functions in crypt.c */

const void FAR_BSS *findCapabilityInfo( const void FAR_BSS *capabilityInfoPtr,
										const CRYPT_ALGO cryptAlgo );
void copyCapabilityInfo( const void FAR_BSS *capabilityInfoPtr,
						 CRYPT_QUERY_INFO *cryptQueryInfo );

/* Prototypes for functions in cryptmis.c */

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

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

/* Initialise and down any devices we're working with */

void deviceInitFortezza( void );
void deviceEndFortezza( void );
void deviceInitPKCS11( void );
void deviceEndPKCS11( void );

void initDevices( void )
	{
#if defined( __WINDOWS__ ) && !defined( NT_DRIVER )
	deviceInitFortezza();
#endif /* __WINDOWS__ && !NT_DRIVER */
#ifdef DEV_PKCS11
	deviceInitPKCS11();
#endif /* DEV_PKCS11 */
	}

void shutdownDevices( void )
	{
#if defined( __WINDOWS__ ) && !defined( NT_DRIVER )
	deviceEndFortezza();
#endif /* __WINDOWS__ && !NT_DRIVER */
#ifdef DEV_PKCS11
	deviceEndPKCS11();
#endif /* DEV_PKCS11 */
	}

/* 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 which
	   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 which passed the FIPS 140 tests, we can't
	   go any further */
	zeroise( data, length );
	assert( NOTREACHED );
	return( CRYPT_ERROR_RANDOM );
	}

/****************************************************************************
*																			*
*								Device API Functions						*
*																			*
****************************************************************************/

/* Default object creation routines used when the device code doesn't set
   anything up */

int createContext( MESSAGE_CREATEOBJECT_INFO *createInfo,
				   const void *auxDataPtr, const int auxValue );

static const CREATEOBJECT_FUNCTION_INFO defaultCreateFunctions[] = {
	{ OBJECT_TYPE_CONTEXT, createContext },
	{ OBJECT_TYPE_NONE, NULL }
	};

/* Handle a message sent to a device object */

static int deviceMessageFunction( const CRYPT_DEVICE cryptDevice,
								  const RESOURCE_MESSAGE_TYPE message,
								  void *messageDataPtr,
								  const int messageValue )
	{
	DEVICE_INFO *deviceInfoPtr;

	getCheckInternalResource( cryptDevice, deviceInfoPtr, OBJECT_TYPE_DEVICE );

	/* Process the destroy object message */
	if( message == RESOURCE_MESSAGE_DESTROY )
		{
		/* Shut down the device if required */
		if( deviceInfoPtr->flags & DEVICE_ACTIVE && \
			deviceInfoPtr->shutdownFunction != NULL )
			deviceInfoPtr->shutdownFunction( deviceInfoPtr );

		/* Delete the objects locking variables and the object itself */
		unlockResource( deviceInfoPtr );
		deleteResourceLock( deviceInfoPtr );
		zeroise( deviceInfoPtr, sizeof( DEVICE_INFO ) );
		free( deviceInfoPtr );

		return( CRYPT_OK );
		}

	/* Process attribute get/set/delete messages */
	if( message == RESOURCE_MESSAGE_SETATTRIBUTE )
		{
		int status;

		/* If it's an initialisation message, there's nothing to do */
		if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
			unlockResourceExit( deviceInfoPtr, CRYPT_OK );

		/* Send the control information to the device */
		status = deviceInfoPtr->controlFunction( deviceInfoPtr, messageValue,
								NULL, *( ( int * ) messageDataPtr ), NULL, 0 );
		unlockResourceExit( deviceInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_SETATTRIBUTE_S )
		{
		const RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
		int status;

		/* Make sure the device which can handle device control attributes */
		if( deviceInfoPtr->controlFunction == NULL )
			unlockResourceExit( deviceInfoPtr, CRYPT_ARGERROR_VALUE );

		/* If it's a PIN attribute, make sure that a login is actually
		   required for the device */
		if( ( messageValue == CRYPT_DEVINFO_AUTHENT_USER || \
			  messageValue == CRYPT_DEVINFO_AUTHENT_SUPERVISOR ) && \
			!( deviceInfoPtr->flags & DEVICE_NEEDSLOGIN ) )
			unlockResourceExit( deviceInfoPtr, CRYPT_ERROR_INITED );

		/* If it's a PIN attribute, make sure the supplied PIN is valid */
		if( messageValue == CRYPT_DEVINFO_INITIALISE || \
			messageValue == CRYPT_DEVINFO_AUTHENT_USER || \
			messageValue == CRYPT_DEVINFO_AUTHENT_SUPERVISOR || \
			messageValue == CRYPT_DEVINFO_SET_AUTHENT_USER || \
			messageValue == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR || \
			messageValue == CRYPT_DEVINFO_ZEROISE )
			if( msgData->length < deviceInfoPtr->minPinSize || \
				msgData->length > deviceInfoPtr->maxPinSize )
				unlockResourceExit( deviceInfoPtr, CRYPT_ARGERROR_NUM1 );

		/* Send the control information to the device */
		status = deviceInfoPtr->controlFunction( deviceInfoPtr, messageValue,
									msgData->data, msgData->length, NULL, 0 );
		unlockResourceExit( deviceInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_GETATTRIBUTE )
		{
		int *valuePtr = ( int * ) messageDataPtr;

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

			case CRYPT_ATTRIBUTE_ERRORLOCUS:
				*valuePtr = deviceInfoPtr->errorLocus;
				break;

			case CRYPT_ATTRIBUTE_INT_ERRORCODE:
				*valuePtr = deviceInfoPtr->errorCode;
				break;

			case CRYPT_DEVINFO_LOGGEDIN:
				*valuePtr = ( deviceInfoPtr->flags & DEVICE_LOGGEDIN ) ? \
							TRUE : FALSE;
				break;

			default:
				assert( NOTREACHED );
			}
		unlockResourceExit( deviceInfoPtr, CRYPT_OK );
		}
	if( message == RESOURCE_MESSAGE_GETATTRIBUTE_S )
		{
		RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
		int status = CRYPT_ERROR_NOTAVAIL;

		switch( messageValue )
			{
			case CRYPT_ATTRIBUTE_INT_ERRORMESSAGE:
				if( !*deviceInfoPtr->errorMessage )
					status = CRYPT_ERROR_NOTFOUND;
				else
					status = attributeCopy( msgData, deviceInfoPtr->errorMessage,
											strlen( deviceInfoPtr->errorMessage ) );
				break;

			case CRYPT_DEVINFO_LABEL:
				if( !*deviceInfoPtr->label )
					status = CRYPT_ERROR_NOTFOUND;
				else
					status = attributeCopy( msgData, deviceInfoPtr->label,
											strlen( deviceInfoPtr->label ) );
				break;

			case CRYPT_IATTRIBUTE_RANDOM:
				if( deviceInfoPtr->getRandomFunction != NULL )
					status = getRandomData( deviceInfoPtr, msgData->data,
											msgData->length );
				break;

			case CRYPT_IATTRIBUTE_RANDOM_NZ:
				if( deviceInfoPtr->getRandomFunction != NULL )
					{
					BYTE randomBuffer[ 128 ], *outBuffer = msgData->data;
					int count = msgData->length;

					/* 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 )
						{
						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 );
					}
				break;

			default:
				assert( NOTREACHED );
			}

		unlockResourceExit( deviceInfoPtr, status );
		}

	/* Process action messages */
	if( isMechanismActionMessage( message ) )
		{
		CRYPT_DEVICE localCryptDevice = cryptDevice;
		MECHANISM_FUNCTION mechanismFunction = NULL;
		int status;

		/* Find the function to handle this action and mechanism */
		if( deviceInfoPtr->mechanismFunctions != NULL )
			{
			int i = 0;

			while( deviceInfoPtr->mechanismFunctions[ i ].action != RESOURCE_MESSAGE_NONE )
				{
				if( deviceInfoPtr->mechanismFunctions[ i ].action == message && \
					deviceInfoPtr->mechanismFunctions[ i ].mechanism == messageValue )
					{
					mechanismFunction = \
						deviceInfoPtr->mechanismFunctions[ i ].function;
					break;
					}
				i++;
				}
			}
		if( mechanismFunction == NULL )
			{
			/* If this is the system object and it can't handle this
			   mechanism, we can't go any further */
			unlockResource( deviceInfoPtr );
			if( localCryptDevice == SYSTEM_OBJECT_HANDLE )
				return( CRYPT_ERROR_NOTAVAIL );

			/* This isn't the system object, fall back to the system object
			   and see if it can handle the mechanism.  We do it this way
			   rather than sending the message through the kernel a second
			   time because all the kernel checking of message parameters has
			   already been done (in terms of access control checks, we can
			   always send the message to the system object so this isn't a
			   problem), this saves the overhead of a second, redundant
			   kernel pass */
			getCheckInternalResource( SYSTEM_OBJECT_HANDLE, deviceInfoPtr,
									  OBJECT_TYPE_DEVICE );
			if( deviceInfoPtr->mechanismFunctions != NULL )
				{
				int i = 0;

				while( deviceInfoPtr->mechanismFunctions[ i ].action != RESOURCE_MESSAGE_NONE )
					{
					if( deviceInfoPtr->mechanismFunctions[ i ].action == message && \
						deviceInfoPtr->mechanismFunctions[ i ].mechanism == messageValue )
						{
						mechanismFunction = \
							deviceInfoPtr->mechanismFunctions[ i ].function;
						break;
						}
					i++;
					}
				}
			unlockResource( deviceInfoPtr );
			if( mechanismFunction == NULL )
				return( CRYPT_ERROR_NOTAVAIL );

			/* The system object can handle this mechanism, forward the
			   message on to the appropriate handler */
			return( mechanismFunction( NULL, messageDataPtr ) );
			}

		/* If the message has been sent to the system object, unlock it to
		   allow it to be used by others and dispatch the message */
		if( localCryptDevice == SYSTEM_OBJECT_HANDLE )
			{
			unlockResource( deviceInfoPtr );
			return( mechanismFunction( NULL, messageDataPtr ) );
			}

		/* Send the message to the device */
		status = mechanismFunction( deviceInfoPtr, messageDataPtr );
		unlockResourceExit( deviceInfoPtr, status );
		}

	/* Process messages which check a device.  In some cases a device can act
	   as a keyset, so if the device could store keys of this type we report
	   it as being an appropriate keyset */
	if( message == RESOURCE_MESSAGE_CHECK )
		{
		if( ( messageValue == RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT || \
			  messageValue == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT || \
			  messageValue == RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK || \
			  messageValue == RESOURCE_MESSAGE_CHECK_PKC_SIGN ) && \
			( deviceInfoPtr->type == CRYPT_DEVICE_FORTEZZA || \
			  deviceInfoPtr->type == CRYPT_DEVICE_PKCS11 ) )
			unlockResourceExit( deviceInfoPtr, CRYPT_OK );

		unlockResourceExit( deviceInfoPtr, CRYPT_ARGERROR_OBJECT );
		}

	/* Process messages which lock/unlock an object for exclusive use */
	if( message == RESOURCE_MESSAGE_LOCK )
		/* Exit without unlocking the object.  Any other threads trying to

⌨️ 快捷键说明

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