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

📄 encode.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
		envelopeInfoPtr->dataFlags |= ENVDATA_NEEDSPADDING;
		if( envelopeInfoPtr->dataFlags & ENVDATA_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 
	   we need to begin a new block before we can try and add the padding.
	   This can happen 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 */
	if( needNewSegment )
		{
		status = beginSegment( envelopeInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
			{
			/* We've filled the envelope buffer with the new segment header,
			   we can't copy in anything */
			return( CRYPT_ERROR_OVERFLOW );
			}
		}

	/* Complete the segment if necessary */
	if( !( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE ) || \
		( envelopeInfoPtr->dataFlags & ENVDATA_NEEDSPADDING ) )
		{
		status = completeSegment( envelopeInfoPtr, TRUE );
		if( cryptStatusError( status ) )
			return( status );

		/* If there wasn't sufficient room to add the trailing PKCS #5 
		   padding tell the caller to try again */
		if( envelopeInfoPtr->dataFlags & ENVDATA_NEEDSPADDING )
			return( CRYPT_ERROR_OVERFLOW );
		}

	/* If there's no hashing being performed or we've completed the hashing, 
	   we're done.  In addition unlike CMS, PGP handles authenticated 
	   attributes by extending the hashing of the payload data to cover the 
	   additional attributes, so if we're using the PGP format we can't wrap 
	   up the hashing yet */
	if( !( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE ) || \
		envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
		return( CRYPT_OK );

	/* We've finished processing everything, complete each hash action */
	return( hashEnvelopeData( envelopeInfoPtr->actionList, "", 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) */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int copyToEnvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr,
						   IN_BUFFER_OPT( length ) const BYTE *buffer, 
						   IN_LENGTH_Z const int length )
	{
	BOOLEAN needCompleteSegment = FALSE;
	BYTE *bufPtr;
	int bytesToCopy, status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( length == 0 || isReadPtr( buffer, length ) );

	REQUIRES( sanityCheck( envelopeInfoPtr ) );
	REQUIRES( length >= 0 && length < MAX_INTLENGTH );

	/* 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 the zero byte count to an overflow error if necessary) */
	if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
		return( ( length > 0 ) ? 0 : CRYPT_ERROR_OVERFLOW );

	/* If we're generating a detached signature just hash the data and exit */
	if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
		{
		/* Unlike CMS, PGP handles authenticated attributes by extending the
		   hashing of the payload data to cover the additional attributes
		   so if this is a flush and we're using the PGP format we can't
		   wrap up the hashing yet */
		if( length <= 0 && envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
			return( 0 );

		status = hashEnvelopeData( envelopeInfoPtr->actionList, buffer, 
								   length );
		return( cryptStatusError( status ) ? status : length );
		}

	/* If we're flushing data, wrap up the segment and exit.  An OK status 
	   translates to zero bytes copied */
	if( length <= 0 )
		{
		status = flushEnvelopeData( envelopeInfoPtr );
		return( cryptStatusError( status ) ? status : 0 );
		}

	/* If we're using an explicit payload length make sure that we don't try 
	   and copy in more data than has been explicitly declared */
	if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \
		length > envelopeInfoPtr->segmentSize )
		return( CRYPT_ERROR_OVERFLOW );

	/* If we've just completed a segment, begin a new one before we add any
	   data */
	if( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE )
		{
		status = beginSegment( envelopeInfoPtr );
		if( cryptStatusError( status ) )
			return( ( status == CRYPT_ERROR_OVERFLOW ) ? 0 : status );
		if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
			{
			/* We've filled the envelope buffer with the new segment header,
			   we can't copy in anything */
			return( 0 );
			}
		}

	/* Copy over as much as we can fit into the envelope buffer */
	bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;
	bytesToCopy = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;
	ENSURES( bytesToCopy > 0 && \
			 envelopeInfoPtr->bufPos + \
					bytesToCopy <= envelopeInfoPtr->bufSize );
#ifdef USE_COMPRESSION
	if( envelopeInfoPtr->flags & ENVELOPE_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 )
			{
			/* There was some problem other than the output buffer being
			   full */
			retIntError();
			}

		/* 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 /* USE_COMPRESSION */
		{
		/* We're not using compression */
		if( bytesToCopy > length )
			bytesToCopy = length;
		memcpy( bufPtr, buffer, bytesToCopy );
		envelopeInfoPtr->bufPos += bytesToCopy;

		/* Hash the data if necessary */
		if( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE )
			{
			status = hashEnvelopeData( envelopeInfoPtr->actionList, bufPtr,
									   bytesToCopy );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* If the buffer is full (i.e. 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;
		}

	/* Adjust the bytes-left counter if necessary */
	if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
		envelopeInfoPtr->segmentSize -= bytesToCopy;

	ENSURES( sanityCheck( envelopeInfoPtr ) );

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

	return( bytesToCopy );
	}

/****************************************************************************
*																			*
*								Copy from Envelope							*
*																			*
****************************************************************************/

/* 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 */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int copyFromEnvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
							 OUT_BUFFER( maxLength, length ) BYTE *buffer, 
							 IN_LENGTH const int maxLength, 
							 OUT_LENGTH_Z int *length, 
							 IN_FLAGS( ENVCOPY ) const int flags )
	{
	int bytesToCopy = maxLength, remainder;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( maxLength == 0 || isWritePtr( buffer, maxLength ) );

	REQUIRES( sanityCheck( envelopeInfoPtr ) );
	REQUIRES( maxLength > 0 && maxLength < MAX_INTLENGTH );
	REQUIRES( flags == ENVCOPY_FLAG_NONE );

	/* Clear return values */
	memset( buffer, 0, min( 16, maxLength ) );
	*length = 0;

	/* 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( bytesToCopy > 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.  In
		   addition if we're generating a detached signature the data is
		   communicated out-of-band so there's no segmenting */
		if( !( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) && \
			!( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE ) )
			{
			const int status = completeSegment( envelopeInfoPtr, FALSE );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* Return all of the data that we've got */
		if( envelopeInfoPtr->segmentDataEnd < bytesToCopy )
			bytesToCopy = envelopeInfoPtr->segmentDataEnd;
		}
	remainder = envelopeInfoPtr->bufPos - bytesToCopy;
	ENSURES( bytesToCopy >= 0 && bytesToCopy <= envelopeInfoPtr->bufPos );
	ENSURES( remainder >= 0 && remainder <= envelopeInfoPtr->bufPos );

	/* Copy the data out and move any remaining data down to the start of the
	   buffer  */
	if( bytesToCopy > 0 )
		{
		memcpy( buffer, envelopeInfoPtr->buffer, bytesToCopy );

		/* Move any remaining data down in the buffer */
		if( remainder > 0 )
			{
			memmove( envelopeInfoPtr->buffer,
					 envelopeInfoPtr->buffer + bytesToCopy, remainder );
			}
		envelopeInfoPtr->bufPos = remainder;

		/* Update the segment location information.  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 
		   temporarily go negative at this point when the data from the last
		   completed segment is moved past the start of the buffer.  If this
		   happens we set them to a safe value of zero to ensure that they
		   pass the sanity checks elsewhere in the code */
		envelopeInfoPtr->segmentStart -= bytesToCopy;
		if( envelopeInfoPtr->segmentStart < 0 )
			envelopeInfoPtr->segmentStart = 0;
		envelopeInfoPtr->segmentDataStart -= bytesToCopy;
		if( envelopeInfoPtr->segmentDataStart < 0 )
			envelopeInfoPtr->segmentDataStart = 0;
		envelopeInfoPtr->segmentDataEnd -= bytesToCopy;
		ENSURES( envelopeInfoPtr->segmentDataEnd >= 0 && \
				 envelopeInfoPtr->segmentDataEnd < MAX_INTLENGTH );
		}
	*length = bytesToCopy;

	ENSURES( sanityCheck( envelopeInfoPtr ) );
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Envelope Access Routines						*
*																			*
****************************************************************************/

STDC_NONNULL_ARG( ( 1 ) ) \
void initEnvelopeStreaming( INOUT ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Set the access method pointers */
	envelopeInfoPtr->copyToEnvelopeFunction = copyToEnvelope;
	envelopeInfoPtr->copyFromEnvelopeFunction = copyFromEnvelope;
	}
#endif /* USE_ENVELOPES */

⌨️ 快捷键说明

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