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

📄 cryptenv.c

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

			/* In general we can't add new enveloping information once we've
			   started processing data */
			if( envelopeInfoPtr->state != STATE_PREDATA && \
				!( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
				/* We can't add new information once we've started enveloping */
				return( CRYPT_ERROR_INITED );

			/* Add it to the envelope */
			status = envelopeInfoPtr->addInfo( envelopeInfoPtr,
						CRYPT_ENVINFO_PASSWORD, msgData->data, msgData->length );
			break;

		case CRYPT_ENVINFO_RECIPIENT:
			/* Set the envelope usage type based on the fact that we've been
			   fed a recipient email address */
			if( envelopeInfoPtr->usage != ACTION_NONE && \
				envelopeInfoPtr->usage != ACTION_CRYPT )
				return( CRYPT_ERROR_INITED );
			usage = ACTION_CRYPT;

			/* Make sure there's a keyset available to pull the recipient's
			   key from */
			if( envelopeInfoPtr->iEncryptionKeyset == CRYPT_ERROR )
				{
				setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEYSET_ENCRYPT,
							  CRYPT_ERRTYPE_ATTR_ABSENT );
				return( CRYPT_ERROR_NOTINITED );
				}

			/* Try and read the recipient's key from the keyset */
			setMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_EMAIL, 
							msgData->data, msgData->length, NULL, 0, 
							KEYMGMT_FLAG_USAGE_CRYPT );
			status = krnlSendMessage( envelopeInfoPtr->iEncryptionKeyset,
							RESOURCE_IMESSAGE_KEY_GETKEY, &getkeyInfo, 
							KEYMGMT_ITEM_PUBLICKEY );
			if( cryptStatusOK( status ) )
				{
				/* We've got a key, some keysets may not be able to directly
				   differentiate between encryption and signature keys so we
				   perform an extra check here to make sure it really is an
				   encryptionn-capable key */
				status = krnlSendMessage( getkeyInfo.cryptHandle, 
							RESOURCE_IMESSAGE_CHECK, NULL,
							RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT );
				if( cryptStatusError( status ) )
					{
					setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_PUBLICKEY,
								  CRYPT_ERRTYPE_CONSTRAINT );
					status = CRYPT_ERROR_NOTFOUND;
					}
				}
			if( cryptStatusOK( status ) )
				{
				/* We got the key, add it to the envelope */
				status = envelopeInfoPtr->addInfo( envelopeInfoPtr,
												   CRYPT_ENVINFO_PUBLICKEY,
												   &getkeyInfo.cryptHandle, 0 );
				krnlSendNotifier( getkeyInfo.cryptHandle,
								  RESOURCE_IMESSAGE_DECREFCOUNT );
				}
			break;

		case CRYPT_ENVINFO_TIMESTAMP_AUTHORITY:
			/* Set the envelope usage type based on the fact that we've been
			   fed a TSA URL */
			if( envelopeInfoPtr->usage != ACTION_NONE && \
				envelopeInfoPtr->usage != ACTION_SIGN )
				return( CRYPT_ERROR_INITED );
			usage = ACTION_SIGN;

			/* Add it to the envelope */
			status = envelopeInfoPtr->addInfo( envelopeInfoPtr,
						CRYPT_ENVINFO_TIMESTAMP_AUTHORITY, msgData->data,
						msgData->length );
			break;

		default:
			assert( NOTREACHED );
		}

	/* The action was successfully added, update the usage if necessary */
	if( cryptStatusOK( status ) && usage != ACTION_NONE )
		envelopeInfoPtr->usage = usage;
	return( status );
	}

/****************************************************************************
*																			*
*							Envelope Data Handling Functions				*
*																			*
****************************************************************************/

/* Push data into an envelope */

static int envelopePush( ENVELOPE_INFO *envelopeInfoPtr, void *buffer,
						 const int length, int *bytesCopied )
	{
	int status;

	/* Clear return value */
	*bytesCopied = 0;

	/* If we haven't started processing data yet, handle the initial data
	   specially */
	if( envelopeInfoPtr->state == STATE_PREDATA )
		{
		/* If the envelope buffer hasn't been allocated yet, allocate it now */
		if( envelopeInfoPtr->buffer == NULL )
			{
			if( ( envelopeInfoPtr->buffer = malloc( envelopeInfoPtr->bufSize ) ) == NULL )
				return( CRYPT_ERROR_MEMORY );
			memset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );
			}

		/* Emit the header information into the envelope */
		status = envelopeInfoPtr->emitPreamble( envelopeInfoPtr );
		if( cryptStatusError( status ) )
			{
			if( status != CRYPT_ERROR_OVERFLOW )
				envelopeInfoPtr->errorState = status;
			return( status );
			}

		/* The envelope is ready to process data, move it into the high
		   state */
		krnlSendMessage( envelopeInfoPtr->objectHandle,
						 RESOURCE_IMESSAGE_SETATTRIBUTE,
						 MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );
		envelopeInfoPtr->state = STATE_DATA;
		}

	/* If we're in the main data processing state, add the data and perform
	   any necessary actions on it */
	if( envelopeInfoPtr->state == STATE_DATA )
		{
		if( length )
			{
			/* Copy the data to the envelope buffer, taking blocking
			   requirements into account */
			status = envelopeInfoPtr->copyToEnvelope( envelopeInfoPtr,
													  buffer, length );
			*bytesCopied = status;
			if( cryptStatusError( status ) )
				{
				envelopeInfoPtr->errorState = status;
				return( status );
				}

			return( ( *bytesCopied < length ) ? \
					CRYPT_ERROR_OVERFLOW : CRYPT_OK );
			}

		/* This was a flush, move on to the postdata state */
		envelopeInfoPtr->state = STATE_POSTDATA;
		envelopeInfoPtr->envState = ENVSTATE_NONE;
		}

	assert( envelopeInfoPtr->state == STATE_POSTDATA );

	/* We're past the main data-processing state, emit the postamble */
	status = envelopeInfoPtr->emitPostamble( envelopeInfoPtr );
	if( cryptStatusError( status ) )
		{
		if( status != CRYPT_ERROR_OVERFLOW )
			envelopeInfoPtr->errorState = status;
		return( status );
		}
	envelopeInfoPtr->state = STATE_FINISHED;

	return( CRYPT_OK );
	}

static int deenvelopePush( ENVELOPE_INFO *envelopeInfoPtr, void *buffer,
						   const int length, int *bytesCopied )
	{
	BYTE *bufPtr = ( BYTE * ) buffer;
	int bytesIn = length, status = CRYPT_OK;

	/* Clear return value */
	*bytesCopied = 0;

	/* If we haven't started processing data yet, handle the initial data
	   specially */
	if( envelopeInfoPtr->state == STATE_PREDATA )
		{
		/* Perform any initialisation actions */
		if( envelopeInfoPtr->buffer == NULL )
			{
			/* Allocate the envelope buffer */
			if( ( envelopeInfoPtr->buffer = malloc( envelopeInfoPtr->bufSize ) ) == NULL )
				return( CRYPT_ERROR_MEMORY );
			memset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );

#ifndef NO_PGP
			/* Try and determine what the data format being used is.  If it 
			   looks like PGP data, try and process it as such, otherwise 
			   default to PKCS #7/CMS/S/MIME */
			if( length && ( bufPtr[ 0 ] & 0x80 ) )
				{
				initPGPDeenveloping( envelopeInfoPtr );

				/* It's PGP data, so it won't be segmented */
				envelopeInfoPtr->type = CRYPT_FORMAT_PGP;
				envelopeInfoPtr->flags |= ENVELOPE_NOSEGMENT;
				}
#endif /* NO_PGP */
			}

		/* Since we're processing out-of-band information, just copy it in
		   directly */
		if( bytesIn )
			{
			int bytesToCopy = min( envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos,
								   bytesIn );
			if( bytesToCopy )
				{
				memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
						bufPtr, bytesToCopy );
				envelopeInfoPtr->bufPos += bytesToCopy;
				bytesIn -= bytesToCopy;
				*bytesCopied = bytesToCopy;
				bufPtr += bytesToCopy;
				}
			}

		/* Process the preamble */
		status = envelopeInfoPtr->processPreamble( envelopeInfoPtr );
		if( cryptStatusError( status ) )
			{
			if( status != CRYPT_ERROR_UNDERFLOW )	/* Can recover from this */
				envelopeInfoPtr->errorState = status;
			return( status );
			}

		/* The envelope is ready to process data, move it into the high
		   state */
		krnlSendMessage( envelopeInfoPtr->objectHandle,
						 RESOURCE_IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,
						 CRYPT_IATTRIBUTE_INITIALISED );

		/* Move on to the data-processing state */
		envelopeInfoPtr->state = STATE_DATA;
		}

	/* If we're in the main data processing state, add the data and perform
	   any necessary actions on it */
	if( envelopeInfoPtr->state == STATE_DATA )
		{
		/* If there's data to be copied, copy it into the envelope (if we've
		   come from the predata state, we may have zero bytes to copy if
		   everything was consumed by the preamble processing, or there may
		   be room to copy more in if the preamble processing consumed some
		   of what was present) */
		if( bytesIn )
			{
			/* Copy the data to the envelope */
			*bytesCopied += envelopeInfoPtr->copyToDeenvelope( envelopeInfoPtr,
														bufPtr, bytesIn );
			status = cryptStatusError( *bytesCopied ) ? \
					 *bytesCopied : CRYPT_OK;
			if( cryptStatusError( status ) )
				{
				if( status != CRYPT_ERROR_UNDERFLOW )	/* Can recover from this */
					envelopeInfoPtr->errorState = status;
				return( status );
				}
			bytesIn -= *bytesCopied;
			bufPtr += *bytesCopied;
			}

		/* If we've reached the end of the payload (either by having seen the
		   EOC octets with the indefinite encoding, by having reached the end 
		   of the single segment with the definite encoding, or through an
		   explicit flush for unknown-length data), move on to the postdata 
		   state */
		if( envelopeInfoPtr->endOfContents || \
			( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \
			  !envelopeInfoPtr->segmentSize ) || \
			( envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \
			  envelopeInfoPtr->segmentSize == CRYPT_UNUSED && !length ) )
			{
			envelopeInfoPtr->state = STATE_POSTDATA;
			envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
			}
		}

	/* If we're past the main data-processing state, process the postamble */
	if( envelopeInfoPtr->state == STATE_POSTDATA )
		{
		/* Since we're processing trailer information, just copy it in
		   directly */
		if( bytesIn )
			{
/* The handling of EOC information in all situations is very tricky.  With
   PKCS #5 padded data the contents look like:

		    dataLeft	 bufPos
			v			 v
	[ data ][ pad ][ EOC / EOC ]

   The previous processEOC() would leave bufPos as above, the new version
   moves it down to the same location as dataLeft so that after further
   copying it becomes:

		    dataLeft = bufPos
			v
	[ data ][ EOC ]

   ie it adjusts both dataLeft and bufPos for padding rather than just
   dataLeft.  For the original version, the two code alternatives produced the
   following results

	- 230K encrypted data, indefinite: Second version
	- 230K signed data, indefinite: First version and second version
	- Short signed data, n-4 bytes, then 4 bytes: First version

   The new version works with all self-tests and also with large data amounts.
   This comment has been retained in case a situation is found where it
   doesn't work */
#if 1
			const int bytesToCopy = \
					min( envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos,
						 bytesIn );
			if( bytesToCopy )
				{
				memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
						bufPtr, bytesToCopy );
				envelopeInfoPtr->bufPos += bytesToCopy;
				*bytesCopied += bytesToCopy;
				}
#else
			const int bytesToCopy = \
					min( envelopeInfoPtr->bufSize - envelopeInfoPtr->dataLeft,
						 bytesIn );
			if( bytesToCopy )
				{
				memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,
						bufPtr, bytesToCopy );
				envelopeInfoPtr->bufPos = envelopeInfoPtr->dataLeft + \
										  bytesToCopy;
				*bytesCopied += bytesToCopy;
				}
#endif /* 1 */
			}

		/* Process the postamble.  During this processing we can encounter
		   two special types of recoverable error, CRYPT_ERROR_UNDERFLOW (we
		   need more data to continue) or OK_SPECIAL (we processed all the
		   data, but there's out-of-band information still to go), if it's
		   one of these we don't treat it as a standard error */
		status = envelopeInfoPtr->processPostamble( envelopeInfoPtr );
		if( cryptStatusError( status ) && status != OK_SPECIAL )
			{
			if( status != CRYPT_ERROR_UNDERFLOW )
				envelopeInfoPtr->errorState = status;
			return( status );
			}

		/* If the routine returns OK_SPECIAL then it's processed enough of
		   the postamble for the caller to continue, but there's more to go
		   so we shouldn't change the overall state yet */
		if( status == OK_SPECIAL )
			status = CRYPT_OK;
		else
			/* We've processed all data, we're done unless it's a detached
			   sig with the data supplied out-of-band */
			envelopeInfoPtr->state = \
					( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) ? \
					STATE_EXTRADATA : STATE_FINISHED;

		/* At this point we always exit since the out-of-band data has to be
		   processed in a separate push */
		return( status );
		}

	/* If there's extra out-of-band data present, process it separately.  
	   This is slightly complicated by the fact that we're processing two
	   independent lots of data, so we have to be careful to distinguish
	   between handling of the actual data and handling of the out-of-band 
	   data */
	if( envelopeInfoPtr->state == STATE_EXTRADATA )
		{
		/* We pass this point twice, the first time round we check the state 
		   and if it's DEENVSTATE_DONE (set when processing of the main data 
		   was completed) we reset it to DEENVSTATE_NONE and make sure it's a 
		   flush */
		if( envelopeInfoPtr->deenvState == DEENVSTATE_DONE )
			{
			/* We've finished with the main data, reset the state for the
			   out-of-band data.  Normally we exit here since it's a flush,
			   however if the hash value was supplied externally (which means
			   hashing was never active, since it was done by the caller), 
			   we drop through to the wrap-up, since there's no second flush
			   of payload data to be performed and so the flush applies to
			   both sets of data */
			envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
			if( envelopeInfoPtr->hashActionsActive )
				return( length ? CRYPT_ERROR_BADDATA : CRYPT_OK );
			}

		/* This is just raw data so we feed it directly to the processing
		   function */
		status = envelopeInfoPtr->processExtraData( envelopeInfoPtr, buffer,
													length );
		if( cryptStatusOK( status ) )
			{
			*bytesCopied = length;
			if( !length )
				envelopeInfoPtr->state = STATE_FINISHED;

⌨️ 快捷键说明

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