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

📄 res_denv.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*					cryptlib De-enveloping Information Management			*
*						Copyright Peter Gutmann 1996-2008					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "envelope.h"
  #include "asn1.h"
  #include "asn1_ext.h"
  #include "pgp.h"
#else
  #include "envelope/envelope.h"
  #include "misc/asn1.h"
  #include "misc/asn1_ext.h"
  #include "misc/pgp.h"
#endif /* Compiler-specific includes */

/* The maximum number of content items that we can add to a content list.
   We should use FAILSAFE_ITERATIONS_MED but encrypted messages sent to very 
   large distribution lists can have a number of per-recipient wrapped keys 
   that exceed this value */

#define MAX_CONTENT_ITEMS	FAILSAFE_ITERATIONS_LARGE - 1

#ifdef USE_ENVELOPES

/****************************************************************************
*																			*
*						Content List Management Functions					*
*																			*
****************************************************************************/

/* Check whether more content items can be added to a content list */

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
BOOLEAN moreContentItemsPossible( const CONTENT_LIST *contentListPtr )
	{
	int contentListCount;

	assert( contentListPtr == NULL || \
			isReadPtr( contentListPtr, sizeof( ACTION_LIST ) ) );

	for( contentListCount = 0;
		 contentListPtr != NULL && contentListCount < FAILSAFE_ITERATIONS_LARGE;
		 contentListPtr = contentListPtr->next, contentListCount++ );
	ENSURES_B( contentListCount < FAILSAFE_ITERATIONS_LARGE );

	return( ( contentListCount < MAX_CONTENT_ITEMS ) ? TRUE : FALSE );
	}

/* Create a content list item */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int createContentListItem( OUT_PTR CONTENT_LIST **newContentListItemPtrPtr,
						   INOUT MEMPOOL_STATE memPoolState, 
						   IN_ENUM( CRYPT_FORMAT ) \
							const CRYPT_FORMAT_TYPE formatType,
						   IN_BUFFER_OPT( objectSize ) const void *object, 
						   IN_LENGTH_Z const int objectSize,
							const BOOLEAN isSigObject )
	{
	CONTENT_LIST *newItem;

	assert( isWritePtr( newContentListItemPtrPtr, \
						sizeof( CONTENT_LIST * ) ) );
	assert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );
	assert( objectSize == 0 || isReadPtr( object, objectSize ) );

	REQUIRES( formatType > CRYPT_FORMAT_NONE && \
			  formatType < CRYPT_FORMAT_LAST );
	REQUIRES( ( object == NULL && objectSize == 0 ) || \
			  ( object != NULL && \
				objectSize > 0 && objectSize < MAX_INTLENGTH ) );

	if( ( newItem = getMemPool( memPoolState, \
								sizeof( CONTENT_LIST ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( newItem, 0, sizeof( CONTENT_LIST ) );
	newItem->formatType = formatType;
	newItem->object = object;
	newItem->objectSize = objectSize;
	if( isSigObject )
		{
		newItem->flags = CONTENTLIST_ISSIGOBJ;
		newItem->clSigInfo.iSigCheckKey = CRYPT_ERROR;
		newItem->clSigInfo.iExtraData = CRYPT_ERROR;
		newItem->clSigInfo.iTimestamp = CRYPT_ERROR;
		}
	*newContentListItemPtrPtr = newItem;

	return( CRYPT_OK );
	}

/* Add an item to the content list */

STDC_NONNULL_ARG( ( 1, 2 ) ) \
void appendContentListItem( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							INOUT CONTENT_LIST *contentListItem )
	{
	CONTENT_LIST *contentListPtr = envelopeInfoPtr->contentList;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( contentListPtr == NULL || \
			isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );

	/* Find the end of the list and add the new item */
	if( contentListPtr != NULL )
		{
		int iterationCount = 0;
		
		for( contentListPtr = envelopeInfoPtr->contentList, \
				iterationCount = 0;
			 contentListPtr->next != NULL && \
			   iterationCount < FAILSAFE_ITERATIONS_LARGE;
			contentListPtr = contentListPtr->next, iterationCount++ );
		ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_LARGE );
		}
	insertDoubleListElements( &envelopeInfoPtr->contentList, contentListPtr,
							  contentListItem, contentListItem );
	}

/* Delete a content list */

STDC_NONNULL_ARG( ( 1, 2 ) ) \
void deleteContentList( INOUT MEMPOOL_STATE memPoolState,
						INOUT_PTR CONTENT_LIST **contentListHeadPtrPtr )
	{
	CONTENT_LIST *contentListCursor;
	int iterationCount;

	assert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );
	assert( isWritePtr( contentListHeadPtrPtr, sizeof( CONTENT_LIST * ) ) );

	for( contentListCursor = *contentListHeadPtrPtr, iterationCount = 0;
		 contentListCursor != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_LARGE;
		 iterationCount++ )
		{
		CONTENT_LIST *contentListItem = contentListCursor;

		contentListCursor = contentListCursor->next;

		/* Destroy any attached objects if necessary */
		if( contentListItem->flags & CONTENTLIST_ISSIGOBJ )
			{
			CONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;

			if( sigInfo->iSigCheckKey != CRYPT_ERROR )
				krnlSendNotifier( sigInfo->iSigCheckKey, IMESSAGE_DECREFCOUNT );
			if( sigInfo->iExtraData != CRYPT_ERROR )
				krnlSendNotifier( sigInfo->iExtraData, IMESSAGE_DECREFCOUNT );
			if( sigInfo->iTimestamp != CRYPT_ERROR )
				krnlSendNotifier( sigInfo->iTimestamp, IMESSAGE_DECREFCOUNT );
			}

		/* Erase and free the object buffer if necessary */
		deleteDoubleListElement( contentListHeadPtrPtr, contentListItem );
		if( contentListItem->object != NULL )
			{
			/* Clear the object.  We have to cheat a bit here with pointer
			   casting, the 'const' indicates that the object data is never 
			   modified while it's in the content list but it has to be
			   modified in a manner of speaking when we delete it */
			zeroise( ( void * ) contentListItem->object, 
					 contentListItem->objectSize );
			clFree( "deleteContentList", ( void * ) contentListItem->object );
			}
		zeroise( contentListItem, sizeof( CONTENT_LIST ) );
		freeMemPool( memPoolState, contentListItem );
		}
	ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_LARGE );

	*contentListHeadPtrPtr = NULL;
	}

/****************************************************************************
*																			*
*							Process Signature Data 							*
*																			*
****************************************************************************/

/* Process timestamps */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int processTimestamp( INOUT CONTENT_LIST *contentListPtr, 
							 IN_BUFFER( timestampLength ) const void *timestamp, 
							 IN_LENGTH_MIN( MIN_CRYPT_OBJECTSIZE ) \
								const int timestampLength )
	{
	CRYPT_ENVELOPE iTimestampEnvelope;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	MESSAGE_DATA msgData;
	const int bufSize = max( timestampLength + 128, MIN_BUFFER_SIZE );
	int status;

	assert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
	assert( isReadPtr( timestamp, timestampLength ) );

	REQUIRES( timestampLength >= MIN_CRYPT_OBJECTSIZE && \
			  timestampLength < MAX_INTLENGTH );

	/* Create an envelope to contain the timestamp data.  We can't use the
	   internal enveloping API for this because we want to retain the final
	   envelope and not just recover the data contents (which for a 
	   timestamp will be empty anyway) */
	setMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_ENVELOPE );
	if( cryptStatusError( status ) )
		return( status );
	iTimestampEnvelope = createInfo.cryptHandle;

	/* Push in the timestamp data */
	status = krnlSendMessage( iTimestampEnvelope, IMESSAGE_SETATTRIBUTE,
							  ( void * ) &bufSize, 
							  CRYPT_ATTRIBUTE_BUFFERSIZE );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, ( void * ) timestamp, timestampLength );
		status = krnlSendMessage( iTimestampEnvelope, IMESSAGE_ENV_PUSHDATA,
								  &msgData, 0 );
		}
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( iTimestampEnvelope, IMESSAGE_ENV_PUSHDATA, 
								  &msgData, 0 );
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iTimestampEnvelope, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* We've got the timestamp info in a sub-envelope, remember it for
	   later */
	contentListPtr->clSigInfo.iTimestamp = iTimestampEnvelope;
	return( CRYPT_OK );
	}

/* Process CMS unauthenticated attributes.  We can't handle these as
   standard CMS attributes since the only thing that we're likely to see 
   here is a countersignature, which isn't an attribute in the normal 
   sense */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int processUnauthAttributes( INOUT CONTENT_LIST *contentListPtr,
									IN_BUFFER( unauthAttrLength ) \
										const void *unauthAttr,
									IN_LENGTH_MIN( MIN_CRYPT_OBJECTSIZE ) \
										const int unauthAttrLength )
	{
	STREAM stream;
	int iterationCount = 0, status;

	assert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
	assert( isReadPtr( unauthAttr, unauthAttrLength ) );

	REQUIRES( unauthAttrLength >= MIN_CRYPT_OBJECTSIZE && \
			  unauthAttrLength < MAX_INTLENGTH );

	/* Make sure that the unauthenticated attributes are OK.  Normally this
	   is done when we import the attributes but since we can't import
	   them we have to perform the check explicitly here */
	if( cryptStatusError( checkObjectEncoding( unauthAttr, 
											   unauthAttrLength ) ) )
		return( CRYPT_ERROR_BADDATA );

	/* Process each attribute */
	sMemConnect( &stream, unauthAttr, unauthAttrLength );
	status = readConstructed( &stream, NULL, 1 );
	while( cryptStatusOK( status ) && \
		   sMemDataLeft( &stream ) >= MIN_CRYPT_OBJECTSIZE && \
		   iterationCount++ < FAILSAFE_ITERATIONS_LARGE )
		{
		BYTE oid[ MAX_OID_SIZE + 8 ];
		void *dataPtr;
		int oidLength, length = DUMMY_INIT;

		/* See what we've got */
		readSequence( &stream, NULL );
		status = readEncodedOID( &stream, oid, MAX_OID_SIZE, &oidLength, 
								 BER_OBJECT_IDENTIFIER );
		if( cryptStatusOK( status ) )
			status = readSet( &stream, &length );
		if( cryptStatusError( status ) )
			break;

		/* If it's something that we don't recognise, skip it and continue */
		if( oidLength != sizeofOID( OID_TSP_TSTOKEN ) || \
			memcmp( oid, OID_TSP_TSTOKEN, oidLength ) )
			{
			status = readUniversal( &stream );
			continue;
			}

		/* We've got a timestamp.  We can't really do much with this at the 
		   moment since although it quacks like a countersignature, in the 
		   PKIX tradition it's subtly (and gratuitously) incompatible in 
		   various ways so that it can't be verified as a standard 
		   countersignature (video meliora proboque deteriora sequor).  
		   Amusingly, the RFC actually states that this is a stupid way to 
		   do things.  Specifically, instead of using the normal MUST/SHOULD 
		   it first states that the sensible solution to the problem is to 
		   use a countersignature, and then goes on to mandate something 
		   that isn't a countersignature.  Since this isn't the sensible 
		   solution, it's obviously the stupid one.  QED */
		if( length < MIN_CRYPT_OBJECTSIZE )
			{
			/* It's too short to be a valid timestamp */
			status = CRYPT_ERROR_UNDERFLOW;
			continue;
			}
		status = sMemGetDataBlock( &stream, &dataPtr, length );
		if( cryptStatusOK( status ) )
			status = sSkip( &stream, length );
		if( cryptStatusOK( status ) )
			status = processTimestamp( contentListPtr, dataPtr, length );
		/* Continue in the loop with the cryptStatusOK() check */
		}

⌨️ 快捷键说明

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