📄 cryptenv.c
字号:
/****************************************************************************
* *
* cryptlib Enveloping Routines *
* Copyright Peter Gutmann 1996-2007 *
* *
****************************************************************************/
#include "crypt.h"
#ifdef INC_ALL
#include "envelope.h"
#else
#include "envelope/envelope.h"
#endif /* Compiler-specific includes */
/* The default size for the envelope buffer. On 16-bit systems they're
smaller because of memory and int size limitations */
#if defined( CONFIG_CONSERVE_MEMORY )
#define DEFAULT_BUFFER_SIZE 8192
#elif INT_MAX <= 32767
#define DEFAULT_BUFFER_SIZE 16384
#else
#define DEFAULT_BUFFER_SIZE 32768
#endif /* OS-specific envelope size defines */
/* When pushing and popping data, overflow and underflow errors can be
recovered from by adding or removing data so we don't retain the error
state for these error types */
#define isRecoverableError( status ) \
( ( status ) == CRYPT_ERROR_OVERFLOW || \
( status ) == CRYPT_ERROR_UNDERFLOW )
#ifdef USE_ENVELOPES
/****************************************************************************
* *
* Envelope Data Handling Functions *
* *
****************************************************************************/
/* Push data into an envelope */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int envelopePush( INOUT ENVELOPE_INFO *envelopeInfoPtr,
INOUT_BUFFER_OPT( length, *bytesCopied ) \
const void *buffer,
IN_LENGTH_Z const int length,
OUT_LENGTH_Z int *bytesCopied )
{
int status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( ( buffer == NULL && length == 0 ) || \
isReadPtr( buffer, length ) );
assert( isWritePtr( bytesCopied, sizeof( int ) ) );
REQUIRES( ( buffer == NULL && length == 0 ) || \
( buffer != NULL && length > 0 && length < MAX_INTLENGTH ) );
/* Clear return value */
*bytesCopied = 0;
/* If we haven't started processing data yet, handle the initial data
specially */
if( envelopeInfoPtr->state == STATE_PREDATA )
{
/* Make sure that all of the information that we need to proceed is
present */
status = envelopeInfoPtr->checkMissingInfo( envelopeInfoPtr );
if( cryptStatusError( status ) )
return( status );
/* If the envelope buffer hasn't been allocated yet, allocate it now */
if( envelopeInfoPtr->buffer == NULL )
{
if( ( envelopeInfoPtr->buffer = \
clAlloc( "envelopePush", \
envelopeInfoPtr->bufSize + 8 ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );
}
/* Emit the header information into the envelope */
status = envelopeInfoPtr->processPreambleFunction( envelopeInfoPtr );
if( cryptStatusError( status ) )
{
if( !isRecoverableError( status ) )
envelopeInfoPtr->errorState = status;
return( status );
}
/* The envelope is ready to process data, move it into the high
state */
status = krnlSendMessage( envelopeInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,
CRYPT_IATTRIBUTE_INITIALISED );
if( cryptStatusError( status ) )
{
envelopeInfoPtr->errorState = status;
return( status );
}
/* 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( length > 0 )
{
/* Copy the data to the envelope */
status = envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr,
buffer, length );
if( cryptStatusError( status ) )
{
if( !isRecoverableError( status ) )
envelopeInfoPtr->errorState = status;
return( status );
}
*bytesCopied = 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;
}
ENSURES( envelopeInfoPtr->state == STATE_POSTDATA );
/* We're past the main data-processing state, emit the postamble */
status = envelopeInfoPtr->processPostambleFunction( envelopeInfoPtr );
if( cryptStatusError( status ) )
{
if( !isRecoverableError( status ) )
envelopeInfoPtr->errorState = status;
return( status );
}
envelopeInfoPtr->state = STATE_FINISHED;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int deenvelopePush( INOUT ENVELOPE_INFO *envelopeInfoPtr,
INOUT_BUFFER_OPT( length, *bytesCopied ) \
const void *buffer,
IN_LENGTH_Z const int length,
OUT_LENGTH_Z int *bytesCopied )
{
BYTE *bufPtr = ( BYTE * ) buffer;
int bytesIn = length, status = CRYPT_OK;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( ( buffer == NULL && length == 0 ) || \
isReadPtr( buffer, length ) );
assert( isWritePtr( bytesCopied, sizeof( int ) ) );
REQUIRES( ( buffer == NULL && length == 0 ) || \
( buffer != NULL && length > 0 && length < MAX_INTLENGTH ) );
/* 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 = \
clAlloc( "deenvelopePush", \
envelopeInfoPtr->bufSize + 8 ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );
#ifdef USE_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 > 0 && ( bufPtr[ 0 ] & 0x80 ) )
{
/* When we initially created the envelope we defaulted to CMS
formatting so we have to select PGP de-enveloping before
we can continue */
envelopeInfoPtr->type = CRYPT_FORMAT_PGP;
initPGPDeenveloping( envelopeInfoPtr );
}
#endif /* USE_PGP */
}
/* Since we're processing out-of-band information, just copy it in
directly */
if( bytesIn > 0 )
{
const int bytesToCopy = min( envelopeInfoPtr->bufSize - \
envelopeInfoPtr->bufPos, bytesIn );
ENSURES( bytesToCopy >= 0 && bytesToCopy <= length && \
envelopeInfoPtr->bufPos + \
bytesToCopy <= envelopeInfoPtr->bufSize );
if( bytesToCopy > 0 )
{
memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
bufPtr, bytesToCopy );
envelopeInfoPtr->bufPos += bytesToCopy;
bytesIn -= bytesToCopy;
*bytesCopied = bytesToCopy;
bufPtr += bytesToCopy;
}
}
/* Process the preamble */
status = envelopeInfoPtr->processPreambleFunction( envelopeInfoPtr );
if( cryptStatusError( status ) )
{
if( !isRecoverableError( status ) )
envelopeInfoPtr->errorState = status;
return( status );
}
/* The envelope is ready to process data, move it into the high
state */
status = krnlSendMessage( envelopeInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,
CRYPT_IATTRIBUTE_INITIALISED );
if( cryptStatusError( status ) )
{
/* The envelope may already have been moved into the high state
as a side-effect of adding de-enveloping information (whether
the transition occurs here or in res_denv.c depends on the
order in which the caller performs operations) so if we get a
permission error it's means that we're already in the high
state and we can ignore it */
if( status != CRYPT_ERROR_PERMISSION )
{
envelopeInfoPtr->errorState = status;
return( status );
}
status = CRYPT_OK;
}
/* 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 now if the preamble processing consumed
some of what was present */
if( bytesIn > 0 )
{
/* Copy the data to the envelope */
const int byteCount = \
envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr,
bufPtr, bytesIn );
if( cryptStatusError( byteCount ) )
{
if( !isRecoverableError( byteCount ) )
envelopeInfoPtr->errorState = byteCount;
return( byteCount );
}
*bytesCopied += byteCount;
bytesIn -= byteCount;
bufPtr += byteCount;
}
/* If we've reached the end of the payload (either by having seen the
EOC octets with the indefinite encoding or by having reached the
end of the single segment with the definite encoding), move on to
the postdata state */
if( ( envelopeInfoPtr->dataFlags & ENVDATA_ENDOFCONTENTS ) || \
( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \
envelopeInfoPtr->segmentSize <= 0 ) )
{
envelopeInfoPtr->state = STATE_POSTDATA;
envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
}
#ifdef USE_PGP
/* Special-case for the wierd non-length-encoding that some PGP
implementations use for compressed data which uses neither a
definite nor indefinite-length encoding but consists of an
implicit "until you run out of input", see the comment in the PGP
readPacketHeader() for more details. To accomodate this lack of
the data's ability to tell us when it's ended, if we're processing
PGP compressed data and there's no length information present and
it's a data flush we assume that that's all there is */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
envelopeInfoPtr->usage == ACTION_COMPRESS && \
envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \
length <= 0 )
{
envelopeInfoPtr->state = STATE_POSTDATA;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -