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

📄 octetstr.c

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

/* Move all segments remaining in the buffer down to the start after the
   data there has been copied out */

static void moveSegments( ENVELOPE_INFO *envelopeInfoPtr, const int length,
						  const int remainder )
	{
	/* Move the data down in the buffer if necessary */
	if( remainder )
		memmove( envelopeInfoPtr->buffer, envelopeInfoPtr->buffer + length,
				 remainder );
	envelopeInfoPtr->bufPos = remainder;

	/* Update the segment location information.  Note that the segment start
	   values track the start position of the last completed segment and
	   aren't updated until we begin a new segment, so they may go negative
	   when the data from the last completed segment is moved past the start
	   of the buffer */
	envelopeInfoPtr->segmentStart -= length;
	envelopeInfoPtr->segmentDataStart -= length;
	envelopeInfoPtr->segmentDataEnd -= length;
	assert( envelopeInfoPtr->segmentDataEnd >= 0 );
	}

/* Copy data into the envelope.  Returns the number of bytes copied, or an
   overflow error if we're trying to flush data and there isn't room to
   perform the flush (this somewhat peculiar case is because the caller
   expects to have 0 bytes copied in this case) */

static int copyToEnvelope( ENVELOPE_INFO *envelopeInfoPtr, 
						   const BYTE *buffer, const int length )
	{
	ACTION_LIST *hashActionPtr;
	BOOLEAN needCompleteSegment = FALSE;
	BYTE *bufPtr;
	int bytesToCopy, status;

	/* If we're trying to copy into a full buffer, return a count of 0 bytes
	   unless we're trying to flush the buffer (the calling routine may
	   convert this to an overflow error if necessary) */
	if( envelopeInfoPtr->bufPos == envelopeInfoPtr->bufSize )
		return( ( length ) ? 0 : CRYPT_ERROR_OVERFLOW );

	/* If we're generating a detached signature, just hash the data and
	   exit.  We don't have to check for problems with the context at this
	   point since they'll be detected when we try and read the hash value */
	if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
		{
		for( hashActionPtr = envelopeInfoPtr->actionList;
			 hashActionPtr != NULL; hashActionPtr = hashActionPtr->next )
			{
			status = krnlSendMessage( hashActionPtr->iCryptHandle,
									  RESOURCE_IMESSAGE_CTX_HASH,
									  ( void * ) buffer, length );
			if( cryptStatusError( status ) )
				return( status );
			}
		return( length );
		}

	/* If we're flushing data, wrap up the segment and exit */
	if( !length )
		{
		BOOLEAN needNewSegment = envelopeInfoPtr->needsPadding;

#ifndef NO_COMPRESSION
		/* If we're using compression, flush any remaining data out of the
		   zStream */
		if( envelopeInfoPtr->zStreamInited )
			{
			/* If we've just completed a segment, begin a new one.  This
			   action is slightly anomalous in that normally a flush can't
			   add more data to the envelope and so we'd never need to start
			   a new segment during a flush, however since we can have
			   arbitrarily large amounts of data trapped in subspace via zlib
			   we need to be able to handle starting new segments at this
			   point */
			if( envelopeInfoPtr->segmentComplete )
				{
				status = beginSegment( envelopeInfoPtr );
				if( cryptStatusError( status ) )
					return( status );
				if( envelopeInfoPtr->bufPos == envelopeInfoPtr->bufSize )
					return( CRYPT_ERROR_OVERFLOW );
				}

			/* Flush any remaining compressed data into the envelope buffer */
			bytesToCopy = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;
			envelopeInfoPtr->zStream.next_in = NULL;
			envelopeInfoPtr->zStream.avail_in = 0;
			envelopeInfoPtr->zStream.next_out = envelopeInfoPtr->buffer + \
												envelopeInfoPtr->bufPos;
			envelopeInfoPtr->zStream.avail_out = bytesToCopy;
			status = deflate( &envelopeInfoPtr->zStream, Z_FINISH );
			if( status != Z_STREAM_END && status != Z_OK )
				/* There was some problem other than the output buffer being
				   full */
				return( CRYPT_ERROR_FAILED );

			/* Adjust the status information based on the data flushed out
			   of the zStream.  We don't need to check for the output buffer
			   being full because this case is already handled by the check
			   of the deflate() return value */
			envelopeInfoPtr->bufPos += bytesToCopy - \
									   envelopeInfoPtr->zStream.avail_out;
			assert( envelopeInfoPtr->bufPos >= 0 && \
					envelopeInfoPtr->bufPos <= envelopeInfoPtr->bufSize );

			/* If we didn't finish flushing data because the output buffer is
			   full, complete the segment and tell the caller they need to pop
			   some data */
			if( status == Z_OK )
				{
				status = completeSegment( envelopeInfoPtr, TRUE );
				return( cryptStatusError( status ) ? \
						status : CRYPT_ERROR_OVERFLOW );
				}
			}
#endif /* NO_COMPRESSION */

		/* If we're encrypting data with a block cipher, we need to add PKCS
		   #5 padding at the end of the last block */
		if( envelopeInfoPtr->blockSize > 1 )
			{
			envelopeInfoPtr->needsPadding = TRUE;
			if( envelopeInfoPtr->segmentComplete )
				/* The current segment has been wrapped up, we need to begin
				   a new segment to contain the padding */
				needNewSegment = TRUE;
			}

		/* If we're carrying over the padding requirement from a previous
		   block (which happens if there was data left after the previous
		   segment was completed or if the addition of padding would have
		   overflowed the buffer when the segment was completed, in other
		   words if the needPadding flag is still set from the previous
		   call), we need to begin a new block before we can try and add the
		   padding */
		if( needNewSegment )
			{
			status = beginSegment( envelopeInfoPtr );
			if( cryptStatusError( status ) )
				return( status );
			if( envelopeInfoPtr->bufPos == envelopeInfoPtr->bufSize )
				return( CRYPT_ERROR_OVERFLOW );
			}

		/* Complete the segment if necessary */
		if( !envelopeInfoPtr->segmentComplete || envelopeInfoPtr->needsPadding )
			{
			status = completeSegment( envelopeInfoPtr, TRUE );
			if( cryptStatusError( status ) )
				return( status );
			}
		if( envelopeInfoPtr->needsPadding )
			return( CRYPT_ERROR_OVERFLOW );

		/* We've finished processing everything, complete each hash action if
		   necessary */
		if( envelopeInfoPtr->hashActionsActive )
			for( hashActionPtr = envelopeInfoPtr->actionList;
				 hashActionPtr != NULL; hashActionPtr = hashActionPtr->next )
				{
				status = krnlSendMessage( hashActionPtr->iCryptHandle,
										  RESOURCE_IMESSAGE_CTX_HASH, "", 0 );
				if( cryptStatusError( status ) )
					return( status );
				}

		return( 0 );
		}

	/* If we've just completed a segment, begin a new one before we add any
	   data */
	if( envelopeInfoPtr->segmentComplete )
		{
		status = beginSegment( envelopeInfoPtr );
		if( cryptStatusError( status ) || \
			envelopeInfoPtr->bufPos == envelopeInfoPtr->bufSize )
			return( 0 );	/* 0 bytes copied */
		}

	/* Copy over as much as we can fit into the buffer */
	bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;
	bytesToCopy = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;
#ifndef NO_COMPRESSION
	if( envelopeInfoPtr->zStreamInited )
		{
		/* Compress the data into the envelope buffer */
		envelopeInfoPtr->zStream.next_in = ( BYTE * ) buffer;
		envelopeInfoPtr->zStream.avail_in = length;
		envelopeInfoPtr->zStream.next_out = bufPtr;
		envelopeInfoPtr->zStream.avail_out = bytesToCopy;
		status = deflate( &envelopeInfoPtr->zStream, Z_NO_FLUSH );
		if( status != Z_OK )
			return( CRYPT_ERROR );

		/* Adjust the status information based on the data copied into the
		   zStream and flushed from the zStream into the buffer */
		envelopeInfoPtr->bufPos += bytesToCopy - \
								   envelopeInfoPtr->zStream.avail_out;
		bytesToCopy = length - envelopeInfoPtr->zStream.avail_in;

		/* If the buffer is full (there's no more room left for further
		   input) we need to close off the segment */
		if( envelopeInfoPtr->zStream.avail_out == 0 )
			needCompleteSegment = TRUE;
		}
	else
#endif /* NO_COMPRESSION */
		{
		/* We're not using compression */
		if( bytesToCopy > length )
			bytesToCopy = length;
		memcpy( bufPtr, buffer, bytesToCopy );
		envelopeInfoPtr->bufPos += bytesToCopy;

		/* Hash the data if necessary.  We don't have to check for problems
		   with the context at this point since they'll be detected when we
		   try and read the hash value */
		if( envelopeInfoPtr->hashActionsActive )
			for( hashActionPtr = envelopeInfoPtr->actionList;
				 hashActionPtr != NULL; hashActionPtr = hashActionPtr->next )
				krnlSendMessage( hashActionPtr->iCryptHandle,
								 RESOURCE_IMESSAGE_CTX_HASH, bufPtr, 
								 bytesToCopy );

		/* If the buffer is full (ie we've been fed more input data than we
		   could copy into the buffer) we need to close off the segment */
		if( bytesToCopy < length )
			needCompleteSegment = TRUE;
		}
	assert( envelopeInfoPtr->bufPos >= 0 );

	/* Close off the segment if necessary */
	if( needCompleteSegment )
		{
		status = completeSegment( envelopeInfoPtr, FALSE );
		if( cryptStatusError( status ) )
			return( status );
		}

	return( bytesToCopy );
	}

/* Copy data from the envelope and begin a new segment in the newly-created
   room.  If called with a zero length value this will create a new segment
   without moving any data.  Returns the number of bytes copied */

static int copyFromEnvelope( ENVELOPE_INFO *envelopeInfoPtr, BYTE *buffer,
							 int length )
	{
	BYTE *bufPtr = envelopeInfoPtr->buffer;
	int remainder;

	/* If the caller wants more data than there is available in the set of
	   completed segments, try to wrap up the next segment to make more data
	   available */
	if( length > envelopeInfoPtr->segmentDataEnd )
		{
		/* Try and complete the segment if necessary.  This may not be
		   possible if we're using a block encryption mode and there isn't
		   enough room at the end of the buffer to encrypt a full block.  If
		   we're generating a detached sig, the data is communicated out-of-
		   band, so there's no segmenting */
		if( !( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) && \
			!envelopeInfoPtr->segmentComplete )
			{
			int status = completeSegment( envelopeInfoPtr, FALSE );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* Return all the data we've got */
		length = min( length, envelopeInfoPtr->segmentDataEnd );
		}
	remainder = envelopeInfoPtr->bufPos - length;
	assert( remainder >= 0 );

	/* Copy the data out and move any remaining data down to the start of the
	   buffer  */
	if( length )
		{
		memcpy( buffer, bufPtr, length );
		moveSegments( envelopeInfoPtr, length, remainder );
		}

	return( length );
	}

/****************************************************************************
*																			*
*						OCTET STRING Decoding Routines						*
*																			*
****************************************************************************/

/* Handle the EOC and PKCS #5 block padding if necessary */

static int processEOC( ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* If we're using a block cipher, undo the PKCS #5 padding which is
	   present at the end of the block */
	if( envelopeInfoPtr->blockSize > 1 )
		{
		const int padSize = \
					envelopeInfoPtr->buffer[ envelopeInfoPtr->bufPos - 1 ];

		if( padSize > envelopeInfoPtr->blockSize )
			/* Data corrupted or wrong key used */
			return( CRYPT_ERROR_BADDATA );
		envelopeInfoPtr->bufPos -= padSize;
		assert( envelopeInfoPtr->bufPos >= 0 );
		}

	/* Remember that we've reached the end of the payload and where the
	   payload ends ("This was the end of the river all right") */
	envelopeInfoPtr->endOfContents = TRUE;
	envelopeInfoPtr->dataLeft = envelopeInfoPtr->bufPos;

	return( CRYPT_OK );
	}

/* Decode the header for the next segment in the buffer.  Returns the number
   of bytes consumed, or an underflow error if more data is required */

static int getNextSegment( ENVELOPE_INFO *envelopeInfoPtr, const BYTE *buffer,
						   const int length )
	{
	SEGHDR_STATE state = envelopeInfoPtr->segHdrState;
	long segmentLength = envelopeInfoPtr->segHdrSegLength;
	int count = envelopeInfoPtr->segHdrCount, bufPos;

	/* If we've already processed the entire payload, don't do anything
	   (this can happen when we're using the definite encoding form, since

⌨️ 快捷键说明

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