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

📄 octetstr.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
			{
			status = getNextSegment( envelopeInfoPtr, bufPtr, length );
			if( cryptStatusError( status ) )
				return( status );
			bufPtr += status;
			length -= status;
			if( envelopeInfoPtr->endOfContents || !length )
				break;		/* EOC reached or all data consumed, exit */
			}

		/* Copy the (possibly encrypted) data into the envelope */
		bytesCopied = copyData( envelopeInfoPtr, bufPtr, length );
		if( cryptStatusError( bytesCopied ) )
			return( bytesCopied );
		bufPtr += bytesCopied;
		length -= bytesCopied;
		assert( envelopeInfoPtr->bufPos <= envelopeInfoPtr->bufSize );
		assert( length >= 0 );
		assert( ( envelopeInfoPtr->segmentSize >= 0 ) || \
				( ( envelopeInfoPtr->flags & ENVELOPE_NOSEGMENT ) && \
				  ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) && \
				  ( envelopeInfoPtr->segmentSize == CRYPT_UNUSED ) ) );
		}
	while( length > 0 && bytesCopied );

	return( oldLength - length );
	}

/* Copy data from the de-enveloping envelope.  Returns the number of bytes
   copied */

static int copyFromDeenvelope( ENVELOPE_INFO *envelopeInfoPtr, BYTE *buffer,
							   int length )
	{
	BYTE *bufPtr = envelopeInfoPtr->buffer;
	const BOOLEAN isLookaheadRead = ( length < 0 ) ? TRUE : FALSE;
	int bytesToCopy, bytesCopied, remainder;
	int oobBytesCopied = 0;

	/* Remember how much data we need to copy */
	bytesToCopy = length = ( length < 0 ) ? -length : length;

	/* If we're verifying a detached sig, the data is communicated out-of-
	   band so there's nothing to copy out */
	if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
		return( 0 );

	/* If there's buffered data from a lookahead read present, insert it into
	   the output stream */
	if( envelopeInfoPtr->oobBufPos )
		{
		oobBytesCopied = min( bytesToCopy, envelopeInfoPtr->oobBufPos );
		memcpy( buffer, envelopeInfoPtr->oobBuffer, oobBytesCopied );
		if( !isLookaheadRead )
			{
			/* If we moved the data out of the OOB buffer, adjust the OOB 
			   buffer contents */
			if( envelopeInfoPtr->oobBufPos > oobBytesCopied )
				memmove( envelopeInfoPtr->oobBuffer, 
						 envelopeInfoPtr->oobBuffer + oobBytesCopied,
						 envelopeInfoPtr->oobBufPos - oobBytesCopied );
			envelopeInfoPtr->oobBufPos -= oobBytesCopied;
			}
		bytesToCopy -= oobBytesCopied;
		length -= oobBytesCopied;
		buffer += oobBytesCopied;
		if( !bytesToCopy )
			return( oobBytesCopied );
		}

	/* If we're using compression, expand the data from the buffer to the
	   output via the zStream */
#ifndef NO_COMPRESSION
	if( envelopeInfoPtr->zStreamInited )
		{
		const int bytesIn = \
			( envelopeInfoPtr->dataLeft && \
			  envelopeInfoPtr->dataLeft < envelopeInfoPtr->bufPos ) ? \
			envelopeInfoPtr->dataLeft : envelopeInfoPtr->bufPos;
		int status;

		/* Decompress the data into the output buffer.  Note that we use the
		   length value to determine the length of the output rather than
		   bytesToCopy since the ratio of bytes in the buffer to bytes of
		   output isn't 1:1 as it is for other content types.
		   
		   When using PGP 2.x-compatible decompression, we have to allow a
		   return status of Z_BUF_ERROR because it uses a compression format
		   from a pre-release version of InfoZip which doesn't include 
		   header or trailer information, so the decompression code can't
		   definitely tell that it's reached the end of its input data but
		   can only report that it can't go any further */
		envelopeInfoPtr->zStream.next_in = bufPtr;
		envelopeInfoPtr->zStream.avail_in = bytesIn;
		envelopeInfoPtr->zStream.next_out = buffer;
		envelopeInfoPtr->zStream.avail_out = length;
		status = inflate( &envelopeInfoPtr->zStream, Z_SYNC_FLUSH );
		if( status != Z_OK && status != Z_STREAM_END && \
			status != Z_BUF_ERROR )
			{
			assert( status != Z_STREAM_ERROR );	/* Parameter error */
			return( ( status == Z_DATA_ERROR ) ? CRYPT_ERROR_BADDATA : \
					( status == Z_MEM_ERROR ) ? CRYPT_ERROR_MEMORY : \
					CRYPT_ERROR_FAILED );
			}

		/* Adjust the status information based on the data copied from the
		   buffer into the zStream (bytesCopied) and the data flushed from
		   the zStream to the output (bytesToCopy) */
		bytesCopied = bytesIn - envelopeInfoPtr->zStream.avail_in;
		bytesToCopy = length - envelopeInfoPtr->zStream.avail_out;
		assert( bytesCopied >= 0 && bytesToCopy >= 0 );

		/* If we consumed all input and there's extra data left after
		   the end of the data stream, it's EOC information, mark that
		   as consumed as well */
		if( !envelopeInfoPtr->zStream.avail_in && \
			envelopeInfoPtr->dataLeft && \
			envelopeInfoPtr->dataLeft < envelopeInfoPtr->bufPos )
			{
			assert( ( envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) || \
					( envelopeInfoPtr->endOfContents && \
					  ( envelopeInfoPtr->bufPos - \
						envelopeInfoPtr->dataLeft == 2 ) ) );
			envelopeInfoPtr->dataLeft = envelopeInfoPtr->bufPos;
			}

		/* If we're doing a lookahead read, we can't just copy the data out
		   as we would for any other content type because we can't undo the
		   decompression step, so we remember the output data in a local 
		   buffer and insert it into the output stream on the next read */
		if( isLookaheadRead )
			{
			assert( envelopeInfoPtr->oobBufPos + length <= OOB_BUFFER_SIZE );
			memcpy( envelopeInfoPtr->oobBuffer + envelopeInfoPtr->oobBufPos,
					buffer, length );
			envelopeInfoPtr->oobBufPos += length;
			}
		}
	else
#endif /* NO_COMPRESSION */
		{
		ACTION_LIST *hashActionPtr;

		/* Copy out as much of the data as we can, making sure we don't 
		   overrun into any following data */
		if( bytesToCopy > envelopeInfoPtr->bufPos )
			bytesToCopy = envelopeInfoPtr->bufPos;
		if( envelopeInfoPtr->dataLeft && \
			bytesToCopy > envelopeInfoPtr->dataLeft )
			bytesToCopy = envelopeInfoPtr->dataLeft;

		/* If we're using a block encryption mode and we haven't seen the 
		   end-of-contents yet and there's no data waiting in the block 
		   buffer (which would mean that there's more data to come), we 
		   can't copy out the last block because it might contain padding */
		if( envelopeInfoPtr->blockSize > 1 && \
			!envelopeInfoPtr->endOfContents && \
			!envelopeInfoPtr->blockBufferPos )
			{
			bytesToCopy -= envelopeInfoPtr->blockSize;
			if( bytesToCopy <= 0 )
				return( 0 );
			}

		/* If we've seen the end-of-contents octets and there's no payload 
		   left to copy out, or if we've ended up with nothing to copy (eg 
		   due to blocking requirements), exit */
		if( ( envelopeInfoPtr->endOfContents && !envelopeInfoPtr->dataLeft ) || \
			!bytesToCopy )
			return( oobBytesCopied );

		/* If we're doing a lookahead read, just copy the data out without 
		   adjusting the read-data values */
		if( isLookaheadRead )
			{
			memcpy( buffer, bufPtr, bytesToCopy );
			return( bytesToCopy );
			}

		/* Hash the payload 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 );

		/* We're not using compression, copy the data across directly */
		memcpy( buffer, bufPtr, bytesToCopy );
		bytesCopied = bytesToCopy;
		}

	/* Move any remaining data down to the start of the buffer  */
	remainder = envelopeInfoPtr->bufPos - bytesCopied;
	assert( remainder >= 0 );
	if( remainder && bytesCopied )
		memmove( bufPtr, bufPtr + bytesCopied, remainder );
	envelopeInfoPtr->bufPos = remainder;

	/* If there's data following the payload, adjust the end-of-payload
	   pointer to reflect the data we've just copied out */
	if( envelopeInfoPtr->dataLeft )
		envelopeInfoPtr->dataLeft -= bytesCopied;
	assert( envelopeInfoPtr->dataLeft >= 0 );

	return( oobBytesCopied + bytesToCopy );
	}

/* Synchronise the deenveloping data stream */

static int syncDeenvelopeData( ENVELOPE_INFO *envelopeInfoPtr,
							   STREAM *stream )
	{
	const int dataStartPos = ( int ) stell( stream );
	const int oldBufPos = envelopeInfoPtr->bufPos;
	const int bytesLeft = sMemDataLeft( stream );
	int bytesCopied;

	/* After the envelope header has been processed, what's left is payload
	   data which requires special processing because of segmenting and
	   decryption and hashing requirements, so we feed it in via a
	   copyToDeenvelope() of the data in the buffer.  This is a rather ugly
	   hack, but it works because we're moving data backwards in the buffer 
	   so there shouldn't be any problems for the rare instances where the 
	   data overlaps (in the worst case (PKCS #7 short definite-length OCTET
	   STRING) we only consume two bytes, the tag and one-byte length, but 
	   for any normal memcpy() which moves forwards through memory this 
	   shouldn't be a problem).

	   Since we're in effect restarting from the payload data, we reset
	   everything which counts to point back to the start of the buffer where
	   we'll be moving the payload data.  We don't have to worry about the
	   copyToDeenvelope() overflowing the envelope since the source is the
	   envelope buffer so the data must fit within the envelope */
	envelopeInfoPtr->bufPos = 0;
	if( !bytesLeft )
		{
		/* Handle the special case of the data ending at exactly this point */
		sseek( stream, 0 );
		return( CRYPT_ERROR_UNDERFLOW );
		}
	sMemDisconnect( stream );
	sMemConnect( stream, envelopeInfoPtr->buffer, bytesLeft );
	bytesCopied = envelopeInfoPtr->copyToDeenvelope( envelopeInfoPtr,
							envelopeInfoPtr->buffer + dataStartPos, bytesLeft );
	if( cryptStatusError( bytesCopied ) )
		{
		/* Undo the buffer position reset.  This isn't 100% effective if 
		   there are multiple segments present and we hit an error after 
		   we've copied down enough data to overwrite what's at the start, 
		   but in most cases it allows us to undo the copyToEnvelope() - if 
		   the data is corrupted we won't get any further anyway */
		envelopeInfoPtr->bufPos = oldBufPos;
		return( bytesCopied );
		}

	/* If we've reached the end of the payload, remember where the payload
	   ends.  If there's anything which followed the payload, we need to move
	   it down to the end of the decoded payload data, since
	   copyToDeenvelope() stops copying as soon as it hits the end-of-
	   contents octets */
	if( envelopeInfoPtr->endOfContents && bytesCopied < bytesLeft )
		{
		const int bytesToCopy = bytesLeft - bytesCopied;

		memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,
				envelopeInfoPtr->buffer + bytesCopied + dataStartPos,
				bytesToCopy );
		envelopeInfoPtr->bufPos = envelopeInfoPtr->dataLeft + bytesToCopy;
		}

	return( CRYPT_OK );
	}

/* Process additional out-of-band data which doesn't get copied into/out of
   the de-enveloping envelope */

static int processExtraData( ENVELOPE_INFO *envelopeInfoPtr, 
							 const void *buffer, const int length )
	{
	ACTION_LIST *hashActionPtr;
	int status;

	/* If the hash value was supplied externally (which means there's 
	   nothing for us to hash, since it's already been done by the caller),
	   there won't be any hash actions active and we can return immediately */
	if( !envelopeInfoPtr->hashActionsActive )
		return( length ? CRYPT_ERROR_BADDATA : CRYPT_OK );

	/* The enveloping code uses a null buffer to signify a flush, but the 
	   lower-level encryption actions don't allow a null buffer */
	if( buffer == NULL )
		buffer = "";

	/* Hash the data or wrap up the hashing as appropriate */
	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 );
		}

	/* If we've finished the hashing, clear the hashing active flag to 
	   prevent data from being hashed again if it's processed by other 
	   code such as copyFromDeenvelope() */
	if( !length )
		envelopeInfoPtr->hashActionsActive = FALSE;

	return( CRYPT_OK );
	}

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

void initDataStreaming( ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Set the access method pointers */
	envelopeInfoPtr->copyToEnvelope = copyToEnvelope;
	envelopeInfoPtr->copyFromEnvelope = copyFromEnvelope;
	envelopeInfoPtr->copyToDeenvelope = copyToDeenvelope;
	envelopeInfoPtr->copyFromDeenvelope = copyFromDeenvelope;
	envelopeInfoPtr->syncDeenvelopeData = syncDeenvelopeData;
	envelopeInfoPtr->processExtraData = processExtraData;
	}

⌨️ 快捷键说明

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