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

📄 cryptenv.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						cryptlib Enveloping Routines						*
*					  Copyright Peter Gutmann 1996-2003						*
*																			*
****************************************************************************/

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

#ifdef USE_ENVELOPES

/* The default size for the envelope buffer.  On 16-bit systems they're
   smaller because of memory and int size limitations */

#if defined( CONFIG_CONSERVE_MEMORY )
  #define DEFAULT_BUFFER_SIZE		8192
#elif INT_MAX <= 32767
  #define DEFAULT_BUFFER_SIZE		16384
#else
  #define DEFAULT_BUFFER_SIZE		32768
#endif /* OS-specific envelope size defines */

/* When pushing and popping data, overflow and underflow errors can be
   recovered from by adding or removing data, so we don't retain the error
   state for these error types */

#define isRecoverableError( status ) \
		( ( status ) == CRYPT_ERROR_OVERFLOW || \
		  ( status ) == CRYPT_ERROR_UNDERFLOW )

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Instantiate a cert chain from a collection of certs */

static int instantiateCertChain( const ENVELOPE_INFO *envelopeInfoPtr,
								 CONTENT_LIST *contentListItem )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int status;

	assert( contentListItem->flags & CONTENTLIST_ISSIGOBJ );

	/* Instantiate the cert chain.  Since this isn't a true cert chain (in 
	   the sense of being degenerate PKCS #7 SignedData) but only a 
	   context-tagged SET OF Certificate, we notify the cert management code 
	   of this when it performs the import */
	setMessageCreateObjectIndirectInfo( &createInfo, 
				envelopeInfoPtr->auxBuffer, envelopeInfoPtr->auxBufSize,
				CRYPT_ICERTTYPE_CMS_CERTSET );
	if( contentListItem->issuerAndSerialNumber == NULL )
		{
		createInfo.arg2 = CRYPT_IKEYID_KEYID;
		createInfo.strArg2 = contentListItem->keyID;
		createInfo.strArgLen2 = contentListItem->keyIDsize;
		}
	else
		{
		createInfo.arg2 = CRYPT_IKEYID_ISSUERANDSERIALNUMBER;
		createInfo.strArg2 = contentListItem->issuerAndSerialNumber;
		createInfo.strArgLen2 = contentListItem->issuerAndSerialNumberSize;
		}
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusOK( status ) )
		contentListItem->clSigInfo.iSigCheckKey = createInfo.cryptHandle;
	return( status );
	}

/* Move the envelope component cursor */

static int moveCursor( ENVELOPE_INFO *envelopeInfoPtr, const int value )
	{
	if( envelopeInfoPtr->contentList == NULL )
		return( CRYPT_ERROR_NOTFOUND );	/* Nothing to move the cursor to */

	switch( value )
		{
		case CRYPT_CURSOR_FIRST:
			envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentList;
			break;

		case CRYPT_CURSOR_PREVIOUS:
			if( envelopeInfoPtr->contentListCurrent == NULL || \
				envelopeInfoPtr->contentListCurrent == envelopeInfoPtr->contentList )
				return( CRYPT_ERROR_NOTFOUND );
			else
				{
				CONTENT_LIST *contentListPtr = envelopeInfoPtr->contentList;

				/* Find the previous element in the list */
				while( contentListPtr->next != envelopeInfoPtr->contentListCurrent )
					contentListPtr = contentListPtr->next;
				envelopeInfoPtr->contentListCurrent = contentListPtr;
				}
			break;

		case CRYPT_CURSOR_NEXT:
			if( envelopeInfoPtr->contentListCurrent == NULL || \
				envelopeInfoPtr->contentListCurrent->next == NULL )
				return( CRYPT_ERROR_NOTFOUND );
			envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentListCurrent->next;
			break;

		case CRYPT_CURSOR_LAST:
			envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentList;
			while( envelopeInfoPtr->contentListCurrent->next != NULL )
				envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentListCurrent->next;
			break;

		default:
			return( CRYPT_ARGERROR_NUM1 );
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Envelope Attribute Handling Functions				*
*																			*
****************************************************************************/

/* Exit after setting extended error information */

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

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

static int exitErrorNotInited( ENVELOPE_INFO *envelopeInfoPtr,
							   const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	return( exitError( envelopeInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, 
					   CRYPT_ERROR_NOTINITED ) );
	}

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

/* Handle data sent to or read from an envelope object */

static int processGetAttribute( ENVELOPE_INFO *envelopeInfoPtr,
								void *messageDataPtr, const int messageValue )
	{
	int *valuePtr = ( int * ) messageDataPtr, status;

	/* Generic attributes are valid for all envelope types */
	if( messageValue == CRYPT_ATTRIBUTE_BUFFERSIZE )
		{
		*valuePtr = envelopeInfoPtr->bufSize;
		return( CRYPT_OK );
		}
	if( messageValue == CRYPT_ATTRIBUTE_ERRORTYPE )
		{
		*valuePtr = envelopeInfoPtr->errorType;
		return( CRYPT_OK );
		}
	if( messageValue == CRYPT_ATTRIBUTE_ERRORLOCUS )
		{
		*valuePtr = envelopeInfoPtr->errorLocus;
		return( CRYPT_OK );
		}

	/* If we're de-enveloping PGP data, make sure that the attribute is valid 
	   for PGP envelopes.  We can't perform this check via the ACLs because 
	   the data type isn't known at envelope creation time, so there's a 
	   single generic de-envelope type for which the ACLs allow the union of 
	   all de-enveloping attribute types.  The following check weeds out the 
	   ones that don't work for PGP */
	if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
		messageValue == CRYPT_ENVINFO_SIGNATURE_EXTRADATA )
		return( CRYPT_ARGERROR_VALUE );

	/* Make sure that the attribute is valid for this envelope type and state */
	switch( messageValue )
		{
		case CRYPT_OPTION_ENCR_ALGO:
		case CRYPT_OPTION_ENCR_HASH:
		case CRYPT_OPTION_ENCR_MAC:
			/* Algorithm types are valid only for enveloping */
			if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
				return( CRYPT_ARGERROR_OBJECT );
			break;
					
		case CRYPT_ENVINFO_CURRENT_COMPONENT:
		case CRYPT_ENVINFO_SIGNATURE_RESULT:
		case CRYPT_ENVINFO_SIGNATURE:
		case CRYPT_ENVINFO_SIGNATURE_EXTRADATA:
			/* The signature key and extra data is read-only for de-
			   enveloping, write-only for enveloping, which can't be checked 
			   by the more general kernel checks (the current-component and 
			   sig-result attributes are de-enveloping only, so they are 
			   checked) */
			if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
				return( CRYPT_ARGERROR_OBJECT );

			/* The following check isn't strictly necessary since we can get 
			   some information as soon as it's available, but it leads to 
			   less confusion (for example without this check we can get 
			   signer info long before we can get the signature results, 
			   which could be misinterpreted to mean the signature is bad) 
			   and forces the caller to do things cleanly */
			if( envelopeInfoPtr->usage == ACTION_SIGN && \
				envelopeInfoPtr->state != STATE_FINISHED )
				return( CRYPT_ERROR_INCOMPLETE );

			/* We're querying something that resides in the content list, 
			   make sure that there's a content list present.  If it's 
			   present but nothing is selected, select the first entry */
			if( envelopeInfoPtr->contentListCurrent == NULL )
				{
				if( envelopeInfoPtr->contentList == NULL )
					return( exitErrorNotFound( envelopeInfoPtr, 
											   messageValue ) );
				envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentList;
				}
			break;

#if 0	/* Unused, removed 9/9/03 */
		case CRYPT_IATTRIBUTE_PAYLOADSIZE:
			/* In order to determine the available payload size, we must be 
			   in the finished state (envelope flush successfully processed) 
			   so that all the data is available */
			if( envelopeInfoPtr->state != STATE_FINISHED )
				return( CRYPT_ERROR_INCOMPLETE );

			/* We can only determine the payload size if we're using a 
			   processing mode where this is possible */
			if( envelopeInfoPtr->usage != ACTION_SIGN && \
				envelopeInfoPtr->usage != ACTION_CRYPT )
				return( CRYPT_ERROR_NOTFOUND );
			break;
#endif /* 0 */

		default:
			assert( messageValue == CRYPT_ENVINFO_COMPRESSION || \
					messageValue == CRYPT_ENVINFO_CONTENTTYPE || \
					messageValue == CRYPT_ENVINFO_DETACHEDSIGNATURE || \
					messageValue == CRYPT_IATTRIBUTE_ATTRONLY );
		}

	/* Handle the various information types */
	switch( messageValue )
		{
		case CRYPT_OPTION_ENCR_ALGO:
			if( envelopeInfoPtr->defaultAlgo == CRYPT_ALGO_NONE )
				return( exitErrorNotInited( envelopeInfoPtr, 
											CRYPT_OPTION_ENCR_ALGO ) );
			*valuePtr = envelopeInfoPtr->defaultAlgo;
			return( CRYPT_OK );

		case CRYPT_OPTION_ENCR_HASH:
			if( envelopeInfoPtr->defaultHash == CRYPT_ALGO_NONE )
				return( exitErrorNotInited( envelopeInfoPtr, 
											CRYPT_OPTION_ENCR_HASH ) );
			*valuePtr = envelopeInfoPtr->defaultHash;
			return( CRYPT_OK );

		case CRYPT_OPTION_ENCR_MAC:
			if( envelopeInfoPtr->defaultMAC == CRYPT_ALGO_NONE )
				return( exitErrorNotInited( envelopeInfoPtr, 
											CRYPT_OPTION_ENCR_MAC ) );
			*valuePtr = envelopeInfoPtr->defaultMAC;
			return( CRYPT_OK );

		case CRYPT_ENVINFO_COMPRESSION:
			if( envelopeInfoPtr->usage == ACTION_NONE )
				return( exitErrorNotInited( envelopeInfoPtr, 
											CRYPT_ENVINFO_COMPRESSION ) );
			*valuePtr = ( envelopeInfoPtr->usage == ACTION_COMPRESS ) ? \
						TRUE : FALSE;
			return( CRYPT_OK );

		case CRYPT_ENVINFO_CURRENT_COMPONENT:
			{
			CONTENT_LIST *contentListItem = \
								envelopeInfoPtr->contentListCurrent;
			MESSAGE_KEYMGMT_INFO getkeyInfo;

			assert( contentListItem != NULL );

			/* If we need something other than a private key or we need a
			   private key but there's no keyset present to fetch it from,
			   just report what we need and exit */
			if( contentListItem->envInfo != CRYPT_ENVINFO_PRIVATEKEY || \
				envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )
				{
				*valuePtr = contentListItem->envInfo;
				return( CRYPT_OK );
				}

			/* There's a decryption keyset available, try and get the
			   required key from it.  Since we're accessing the key by 
			   (unique) key ID, there's no real need to specify a preference 
			   for encryption keys.

			   Unlike sig.check keyset access, we retry the access every 
			   time we're called because we may be talking to a device that 
			   has a trusted authentication path which is outside our 
			   control, so that the first read fails if the user hasn't 
			   entered their PIN but a second read once they've entered it 
			   will succeed */
			if( contentListItem->issuerAndSerialNumber == NULL )
				{
				setMessageKeymgmtInfo( &getkeyInfo, 
								( contentListItem->formatType == CRYPT_FORMAT_PGP ) ? \
								CRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID, 
								contentListItem->keyID,
								contentListItem->keyIDsize, NULL, 0,
								KEYMGMT_FLAG_NONE );
				}
			else
				{
				setMessageKeymgmtInfo( &getkeyInfo, 
								CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
								contentListItem->issuerAndSerialNumber,
								contentListItem->issuerAndSerialNumberSize,

⌨️ 快捷键说明

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