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

📄 cryptenv.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
			}
		}

	return( status );
	}

/* Pop data from an envelope */

static int envelopePop( ENVELOPE_INFO *envelopeInfoPtr, void *buffer,
						const int length, int *bytesCopied )
	{
	int bytesOut;

	/* If we're enveloping data, just copy as much as we can to the output */
	if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
		{
		/* Copy the data from the envelope to the output */
		bytesOut = envelopeInfoPtr->copyFromEnvelope( envelopeInfoPtr,
													  buffer, length );
		if( cryptStatusError( bytesOut ) )
			{
			envelopeInfoPtr->errorState = bytesOut;
			return( bytesOut );
			}
		*bytesCopied = bytesOut;
		return( CRYPT_OK );
		}

	/* We're de-enveloping data, if we haven't reached the data yet force a
	   push to try and get to the data.  We can end up with this condition if
	   the caller pushes in deenveloping information and then immediately
	   tries to pop data without an intervening push to resolve the state of
	   the data in the envelope */
	if( envelopeInfoPtr->state == STATE_PREDATA )
		{
		int dummy, status;

		status = deenvelopePush( envelopeInfoPtr, NULL, 0, &dummy );
		if( cryptStatusError( status ) )
			return( status );

		/* If we still haven't got anywhere, return an underflow error */
		if( envelopeInfoPtr->state == STATE_PREDATA )
			return( CRYPT_ERROR_UNDERFLOW );
		}

	/* Copy the data from the envelope to the output */
	bytesOut = envelopeInfoPtr->copyFromDeenvelope( envelopeInfoPtr,
													buffer, length );
	if( cryptStatusError( bytesOut ) )
		{
		envelopeInfoPtr->errorState = bytesOut;
		return( bytesOut );
		}
	*bytesCopied = bytesOut;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Envelope Message Handler					*
*																			*
****************************************************************************/

/* Handle a message sent to an envelope */

static int envelopeMessageFunction( const CRYPT_ENVELOPE cryptEnvelope,
									const RESOURCE_MESSAGE_TYPE message,
									void *messageDataPtr,
									const int messageValue )
	{
	ENVELOPE_INFO *envelopeInfoPtr;

	getCheckInternalResource( cryptEnvelope, envelopeInfoPtr, OBJECT_TYPE_ENVELOPE );

	/* Process destroy object messages */
	if( message == RESOURCE_MESSAGE_DESTROY )
		{
		int status = CRYPT_OK;

		/* Envelope deletion has an extra complication in that instead of
		   simply decrementing its reference count like other objects, we
		   check to see whether the envelope still needs operations performed
		   on it to resolve the state of the data within it (for example if
		   the caller pushes data but doesn't flush it, there will be a few
		   bytes left which can't be popped).  We can't perform this check in
		   the delete function because this may be called from other sections
		   of the code, so we have to do it here.

		   For enveloping, destroying the envelope while it's in any state
		   other than STATE_PREDATA or STATE_FINISHED is regarded as an error.

		   For de-enveloping we have to be more careful, since deenveloping
		   information required to resolve the envelope state could be
		   unavailable, so we shouldn't return an error if something like a
		   signature check remains to be done.  What we therefore do is check
		   to see whether we've processed any data yet and report an error if
		   there's any data left in the envelope or if we destroy it in the
		   middle of processing data */
		if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
			{
			/* If we've got to the point of processing data in the envelope
			   and there's either more to come or some left to pop, we
			   shouldn't be destroying it yet */
			if( envelopeInfoPtr->state == STATE_DATA || \
				( ( envelopeInfoPtr->state == STATE_POSTDATA || \
					envelopeInfoPtr->state == STATE_FINISHED ) && \
				  envelopeInfoPtr->dataLeft ) )
				status = CRYPT_ERROR_INCOMPLETE;
			}
		else
			/* If we're in the middle of processing data, we shouldn't be
			   destroying the envelope yet */
			if( envelopeInfoPtr->state != STATE_PREDATA && \
				envelopeInfoPtr->state != STATE_FINISHED )
				status = CRYPT_ERROR_INCOMPLETE;

		/* Delete the action and content lists */
		deleteActionList( envelopeInfoPtr->preActionList );
		deleteActionList( envelopeInfoPtr->actionList );
		deleteActionList( envelopeInfoPtr->postActionList );
		deleteContentList( envelopeInfoPtr->contentList );

#ifndef NO_COMPRESSION
		/* Delete the zlib compression state information if necessary */
		if( envelopeInfoPtr->zStreamInited )
			if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
				inflateEnd( &envelopeInfoPtr->zStream );
			else
				deflateEnd( &envelopeInfoPtr->zStream );
#endif /* NO_COMPRESSION */

		/* Handle the keyset cleanup by calling the internal keyset close
		   function */
		if( envelopeInfoPtr->iSigCheckKeyset != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iSigCheckKeyset,
							  RESOURCE_IMESSAGE_DECREFCOUNT );
		if( envelopeInfoPtr->iEncryptionKeyset != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iEncryptionKeyset,
							  RESOURCE_IMESSAGE_DECREFCOUNT );
		if( envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iDecryptionKeyset,
							  RESOURCE_IMESSAGE_DECREFCOUNT );

		/* Clean up other envelope objects */
		if( envelopeInfoPtr->iOriginatorChain != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iOriginatorChain,
							  RESOURCE_IMESSAGE_DECREFCOUNT );

		/* Clear and free the buffers if necessary */
		if( envelopeInfoPtr->buffer != NULL )
			{
			zeroise( envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );
			free( envelopeInfoPtr->buffer );
			}
		if( envelopeInfoPtr->auxBuffer != NULL )
			{
			zeroise( envelopeInfoPtr->auxBuffer, envelopeInfoPtr->auxBufSize );
			free( envelopeInfoPtr->auxBuffer );
			}

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

		return( status );
		}

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

		assert( message == RESOURCE_MESSAGE_GETATTRIBUTE || \
				message == RESOURCE_MESSAGE_GETATTRIBUTE_S || \
				message == RESOURCE_MESSAGE_SETATTRIBUTE || \
				message == RESOURCE_MESSAGE_SETATTRIBUTE_S );

		if( message == RESOURCE_MESSAGE_GETATTRIBUTE )
			status = processGetAttribute( envelopeInfoPtr, messageDataPtr,
										  messageValue );
		if( message == RESOURCE_MESSAGE_GETATTRIBUTE_S )
			status = processGetAttributeS( envelopeInfoPtr, messageDataPtr,
										   messageValue );
		if( message == RESOURCE_MESSAGE_SETATTRIBUTE )
			status = processSetAttribute( envelopeInfoPtr, messageDataPtr,
										  messageValue );
		if( message == RESOURCE_MESSAGE_SETATTRIBUTE_S )
			status = processSetAttributeS( envelopeInfoPtr, messageDataPtr,
										   messageValue );
		unlockResourceExit( envelopeInfoPtr, status );
		}

	/* 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
		   use the object after this point will be blocked */
		return( CRYPT_OK );
	if( message == RESOURCE_MESSAGE_UNLOCK )
		{
		/* "Wenn drei Leute in ein Zimmer reingehen und fuenf kommen raus,
			dann muessen erst mal zwei wieder reingehen bis das Zimmer leer
			ist" */
		unlockResource( envelopeInfoPtr );	/* Undo RESOURCE_MESSAGE_LOCK lock */
		unlockResourceExit( envelopeInfoPtr, CRYPT_OK );
		}

	/* Process object-specific messages */
	if( message == RESOURCE_MESSAGE_ENV_PUSHDATA )
		{
		RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
		int bytesCopied, status;

		assert( ( msgData->data == NULL && msgData->length == 0 ) || \
				( msgData->data != NULL && msgData->length > 0 ) );

		/* Make sure everything is in order */
		if( msgData->length == 0 )
			{
			/* If it's a flush, make sure we're in a state where this is
			   valid.  We can only perform a flush on enveloping if we're in
			   the data or postdata state, on deenveloping a flush can
			   happen at any time since the entire payload could be buffered
			   pending the addition of a deenveloping resource, so the
			   envelope goes from pre -> post in one step */
			if( envelopeInfoPtr->state == STATE_FINISHED )
				unlockResourceExit( envelopeInfoPtr, CRYPT_OK );
			if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
				( envelopeInfoPtr->state != STATE_DATA && \
				  envelopeInfoPtr->state != STATE_POSTDATA ) )
				unlockResourceExit( envelopeInfoPtr,
									CRYPT_ERROR_INCOMPLETE );
			}
		if( envelopeInfoPtr->state == STATE_FINISHED )
			unlockResourceExit( envelopeInfoPtr, CRYPT_ERROR_COMPLETE );
		if( envelopeInfoPtr->errorState != CRYPT_OK )
			unlockResourceExit( envelopeInfoPtr,
								envelopeInfoPtr->errorState );
		if( ( ( envelopeInfoPtr->flags & \
				( ENVELOPE_NOSEGMENT & ENVELOPE_ISDEENVELOPE ) ) == ENVELOPE_NOSEGMENT ) && \
			envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
			{
			/* If we're enveloping using a non-segmenting encoding of the 
			   payload, the caller has to explicitly set the payload size 
			   before they can add any data */
			setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_DATASIZE,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}

		/* Send the data to the envelope */
		if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
			status = deenvelopePush( envelopeInfoPtr, msgData->data,
									 msgData->length, &bytesCopied );
		else
			status = envelopePush( envelopeInfoPtr, msgData->data,
								   msgData->length, &bytesCopied );
		msgData->length = bytesCopied;

		unlockResourceExit( envelopeInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_ENV_POPDATA )
		{
		RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
		int bytesCopied, status;

		assert( msgData->data != NULL && msgData->length > 0 );

		/* Make sure everything is in order */
		if( envelopeInfoPtr->errorState != CRYPT_OK )
			unlockResourceExit( envelopeInfoPtr,
								envelopeInfoPtr->errorState );

		/* Get the data from the envelope */
		status = envelopePop( envelopeInfoPtr, msgData->data,
							  msgData->length, &bytesCopied );
		msgData->length = bytesCopied;

		unlockResourceExit( envelopeInfoPtr, status );
		}

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

/* Create an envelope.  This is a low-level function encapsulated by
   createEnvelope() and used to manage error exits */

static int initEnvelope( CRYPT_ENVELOPE *iCryptEnvelope,
						 const CRYPT_USER cryptOwner,
						 const CRYPT_FORMAT_TYPE formatType,
						 ENVELOPE_INFO **envelopeInfoPtrPtr )
	{
	ENVELOPE_INFO *envelopeInfoPtr;
	const BOOLEAN isDeenvelope = ( formatType == CRYPT_FORMAT_AUTO ) ? \
								 TRUE : FALSE;
	const int subType = \
			isDeenvelope ? SUBTYPE_ENV_DEENV : \
			( formatType == CRYPT_FORMAT_PGP ) ? \
				SUBTYPE_ENV_ENV_PGP : SUBTYPE_ENV_ENV;
	void *auxBuffer;
	int status;

	/* Clear the return values */
	*iCryptEnvelope = CRYPT_ERROR;
	*envelopeInfoPtrPtr = NULL;

	/* If PGP support is disabled, we can't specify PGP as a target format */
#ifdef NO_PGP
	if( createInfo->arg1 == CRYPT_FORMAT_PGP )
		return( CRYPT_ARGERROR_NUM1 );
#endif /* NO_PGP */

	/* Allocate the auxiliary buffer (for enveloping only) */
	if( !isDeenvelope && \
		( auxBuffer = malloc( DEFAULT_AUXBUFFER_SIZE ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* Create the envelope object */
	status = krnlCreateObject( ( void ** ) &envelopeInfoPtr, cryptOwner,
							   OBJECT_TYPE_ENVELOPE, subType,
							   sizeof( ENVELOPE_INFO ), 0, 0,
							   envelopeMessageFunction );
	if( cryptStatusError( status ) )
		{
		if( !isDeenvelope )
			free( auxBuffer );
		return( status );
		}
	initResourceLock( envelopeInfoPtr );
	lockResource( envelopeInfoPtr );
	*envelopeInfoPtrPtr = envelopeInfoPtr;
	*iCryptEnvelope = envelopeInfoPtr->objectHandle = status;
	envelopeInfoPtr->ownerHandle = cryptOwner;
	envelopeInfoPtr->bufSize = DEFAULT_BUFFER_SIZE;
	if( isDeenvelope )
		envelopeInfoPtr->flags = ENVELOPE_ISDEENVELOPE;
	else
		{
		envelopeInfoPtr->auxBuffer = auxBuffer;
		memset( envelopeInfoPtr->auxBuffer, 0, DEFAULT_AUXBUFFER_SIZE );
		envelopeInfoPtr->auxBufSize = DEFAULT_AUXBUFFER_SIZE;
		}
	envelopeInfoPtr->type = formatType;
	envelopeInfoPtr->state = STATE_PREDATA;

	/* Set up any internal objects to contain invalid handles */
	envelopeInfoPtr->iCryptContext = \
		envelopeInfoPtr->iOriginatorChain = CRYPT_ERROR;
	envelopeInfoPtr->iSigCheckKeyset = envelopeInfoPtr->iEncryptionKeyset = \
		envelopeInfoPtr->iDecryptionKeyset = CRYPT_ERROR;
	envelopeInfoPtr->payloadSize = CRYPT_UNUSED;

	/* Set up the enveloping methods */
	if( formatType == CRYPT_FORMAT_PGP )
		initPGPEnveloping( envelopeInfoPtr );
	else
		initCMSEnveloping( envelopeInfoPtr );
	initDataStreaming( envelopeInfoPtr );
	initResourceHandling( envelopeInfoPtr );

	/* Set up the de-enveloping methods.  We default to PKCS #7/CMS/SMIME, 
	   if the data is in some other format we'll adjust the function 
	   pointers once the user pushes in the first data quantity */
	if( isDeenvelope )
		initCMSDeenveloping( envelopeInfoPtr );

	return( CRYPT_OK );
	}

int createEnvelope( MESSAGE_CREATEOBJECT_INFO *createInfo, 
					const void *auxDataPtr, const int auxValue )
	{
	CRYPT_ENVELOPE iCryptEnvelope;
	ENVELOPE_INFO *envelopeInfoPtr;
	int initStatus, status;

	assert( auxDataPtr == NULL );
	assert( auxValue == 0 );

	/* Perform basic error checking */
	if( createInfo->arg1 <= CRYPT_FORMAT_NONE || \
		createInfo->arg1 >= CRYPT_FORMAT_LAST )
		return( CRYPT_ARGERROR_NUM1 );

	/* Pass the call on to the lower-level open function */
	initStatus = initEnvelope( &iCryptEnvelope, createInfo->cryptOwner,
							   createInfo->arg1, &envelopeInfoPtr );
	if( envelopeInfoPtr == NULL )
		return( initStatus );	/* Create object failed, return immediately */
	if( cryptStatusError( initStatus ) )
		/* The session open failed, make sure the object gets destroyed when
		   we notify the kernel that the setup process is complete */
		krnlSendNotifier( iCryptEnvelope, RESOURCE_IMESSAGE_DESTROY );

	/* We've finished setting up the object-type-specific info, tell the
	   kernel the object is ready for use */
	unlockResource( envelopeInfoPtr );
	status = krnlSendMessage( iCryptEnvelope, RESOURCE_IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
	if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
		return( cryptStatusError( initStatus ) ? initStatus : status );
	createInfo->cryptHandle = iCryptEnvelope;
	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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