📄 cryptenv.c
字号:
{
zeroise( envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );
clFree( "envelopeMessageFunction", envelopeInfoPtr->buffer );
}
if( envelopeInfoPtr->auxBuffer != NULL )
{
zeroise( envelopeInfoPtr->auxBuffer, envelopeInfoPtr->auxBufSize );
clFree( "envelopeMessageFunction", envelopeInfoPtr->auxBuffer );
}
return( status );
}
/* Process attribute get/set/delete messages */
if( isAttributeMessage( message ) )
{
REQUIRES( message == MESSAGE_GETATTRIBUTE || \
message == MESSAGE_GETATTRIBUTE_S || \
message == MESSAGE_SETATTRIBUTE || \
message == MESSAGE_SETATTRIBUTE_S || \
message == MESSAGE_DELETEATTRIBUTE );
REQUIRES( isAttribute( messageValue ) || \
isInternalAttribute( messageValue ) );
if( message == MESSAGE_GETATTRIBUTE )
return( getEnvelopeAttribute( envelopeInfoPtr,
( int * ) messageDataPtr,
messageValue ) );
if( message == MESSAGE_GETATTRIBUTE_S )
return( getEnvelopeAttributeS( envelopeInfoPtr,
( MESSAGE_DATA * ) messageDataPtr,
messageValue ) );
if( message == MESSAGE_SETATTRIBUTE )
{
/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message
with no parameters so we don't pass it down to the attribute-
handling code */
if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
return( CRYPT_OK );
return( setEnvelopeAttribute( envelopeInfoPtr,
*( ( int * ) messageDataPtr ),
messageValue ) );
}
if( message == MESSAGE_SETATTRIBUTE_S )
{
const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
return( setEnvelopeAttributeS( envelopeInfoPtr, msgData->data,
msgData->length, messageValue ) );
}
retIntError();
}
/* Process object-specific messages */
if( message == MESSAGE_ENV_PUSHDATA )
{
MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
const int length = msgData->length;
int bytesCopied, status;
assert( ( msgData->data == NULL && msgData->length == 0 ) || \
( isReadPtr( msgData->data, msgData->length ) ) );
REQUIRES( ( msgData->data == NULL && msgData->length == 0 ) || \
( msgData->data != NULL && \
msgData->length > 0 && msgData->length < MAX_INTLENGTH ) );
/* Unless we're told otherwise, we've copied zero bytes */
msgData->length = 0;
/* Make sure that everything is in order */
if( length == 0 )
{
/* If it's a flush make sure that we're in a state where this is
valid. We can only perform a flush on enveloping if we're in
the data or postdata state, on deenveloping a flush can
happen at any time since the entire payload could be buffered
pending the addition of a deenveloping resource, so the
envelope goes from pre -> post in one step. There is however
one special case in which a push in the pre-data state is
valid and that's when we're creating a zero-length CMS signed
message as a means of communicating authenticated attributes
(of all the standard users of CMS, only SCEP normally does
this). In order to indicate that this special case is in
effect we require that the user set the ENVELOPE_ATTRONLY
flag before pushing data, although for completeness we could
also check the CMS attributes for the presence of SCEP
attributes. The downside of this additional checking is that
it makes any non-SCEP use of signature-only CMS envelopes
impossible */
if( envelopeInfoPtr->state == STATE_FINISHED )
return( CRYPT_OK );
if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
( envelopeInfoPtr->state != STATE_DATA && \
envelopeInfoPtr->state != STATE_POSTDATA ) && \
!( envelopeInfoPtr->state == STATE_PREDATA && \
envelopeInfoPtr->usage == ACTION_SIGN && \
envelopeInfoPtr->type == CRYPT_FORMAT_CMS && \
( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY ) ) )
return( CRYPT_ERROR_INCOMPLETE );
}
else
{
if( envelopeInfoPtr->state == STATE_FINISHED )
return( CRYPT_ERROR_COMPLETE );
}
if( envelopeInfoPtr->errorState != CRYPT_OK )
return( envelopeInfoPtr->errorState );
if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
( envelopeInfoPtr->dataFlags & ENVDATA_NOSEGMENT ) && \
envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
{
/* If we're enveloping using a non-segmenting encoding of the
payload then the caller has to explicitly set the payload
size before they can add any data */
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_DATASIZE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Send the data to the envelope */
if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
status = deenvelopePush( envelopeInfoPtr, msgData->data,
length, &bytesCopied );
else
status = envelopePush( envelopeInfoPtr, msgData->data,
length, &bytesCopied );
if( cryptStatusOK( status ) )
msgData->length = bytesCopied;
else
{
/* In some cases data can be copied even if an error status is
returned. The most usual case is when the error is
recoverable (underflow or overflow), however when we're de-
enveloping we can also copy data but then stall with a
CRYPT_ENVELOPE_RESOURCE notification */
if( ( isRecoverableError( status ) && bytesCopied > 0 ) || \
( ( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
status == CRYPT_ENVELOPE_RESOURCE && bytesCopied > 0 ) )
msgData->length = bytesCopied;
}
return( status );
}
if( message == MESSAGE_ENV_POPDATA )
{
MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
const int length = msgData->length;
int bytesCopied, status;
assert( isWritePtr( msgData->data, msgData->length ) );
REQUIRES( msgData->length > 0 && msgData->length < MAX_INTLENGTH );
/* Unless we're told otherwise, we've copied zero bytes */
msgData->length = 0;
/* Make sure that everything is in order */
if( envelopeInfoPtr->errorState != CRYPT_OK )
return( envelopeInfoPtr->errorState );
/* Get the data from the envelope */
if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
status = deenvelopePop( envelopeInfoPtr, msgData->data,
length, &bytesCopied );
else
status = envelopePop( envelopeInfoPtr, msgData->data,
length, &bytesCopied );
if( cryptStatusOK( status ) )
msgData->length = bytesCopied;
return( status );
}
retIntError();
}
/* Create an envelope. This is a low-level function encapsulated by
createEnvelope() and used to manage error exits */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
static int initEnvelope( OUT_HANDLE_OPT CRYPT_ENVELOPE *iCryptEnvelope,
IN_HANDLE const CRYPT_USER iCryptOwner,
IN_ENUM( CRYPT_FORMAT ) \
const CRYPT_FORMAT_TYPE formatType,
OUT_PTR ENVELOPE_INFO **envelopeInfoPtrPtr )
{
ENVELOPE_INFO *envelopeInfoPtr;
const BOOLEAN isDeenvelope = ( formatType == CRYPT_FORMAT_AUTO ) ? \
TRUE : FALSE;
const int subType = \
isDeenvelope ? SUBTYPE_ENV_DEENV : \
( formatType == CRYPT_FORMAT_PGP ) ? \
SUBTYPE_ENV_ENV_PGP : SUBTYPE_ENV_ENV;
const int storageSize = 3 * sizeof( CONTENT_LIST );
int status;
assert( isWritePtr( iCryptEnvelope, sizeof( CRYPT_ENVELOPE * ) ) );
assert( isWritePtr( envelopeInfoPtrPtr, sizeof( ENVELOPE_INFO * ) ) );
REQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \
isHandleRangeValid( iCryptOwner ) );
REQUIRES( formatType > CRYPT_FORMAT_NONE && \
formatType < CRYPT_FORMAT_LAST_EXTERNAL );
/* Clear return values */
*iCryptEnvelope = CRYPT_ERROR;
*envelopeInfoPtrPtr = NULL;
/* If PGP support is disabled we can't specify PGP as a target format */
#ifndef USE_PGP
if( formatType == CRYPT_FORMAT_PGP )
return( CRYPT_ARGERROR_NUM1 );
#endif /* USE_PGP */
/* Create the envelope object */
status = krnlCreateObject( iCryptEnvelope, ( void ** ) &envelopeInfoPtr,
sizeof( ENVELOPE_INFO ) + storageSize,
OBJECT_TYPE_ENVELOPE, subType,
CREATEOBJECT_FLAG_NONE, iCryptOwner,
ACTION_PERM_NONE_ALL, envelopeMessageFunction );
if( cryptStatusError( status ) )
return( status );
*envelopeInfoPtrPtr = envelopeInfoPtr;
envelopeInfoPtr->objectHandle = *iCryptEnvelope;
envelopeInfoPtr->ownerHandle = iCryptOwner;
envelopeInfoPtr->bufSize = DEFAULT_BUFFER_SIZE;
if( isDeenvelope )
envelopeInfoPtr->flags = ENVELOPE_ISDEENVELOPE;
envelopeInfoPtr->type = formatType;
envelopeInfoPtr->state = STATE_PREDATA;
envelopeInfoPtr->storageSize = storageSize;
initMemPool( envelopeInfoPtr->memPoolState, envelopeInfoPtr->storage,
storageSize );
/* Set up any internal objects to contain invalid handles */
envelopeInfoPtr->iCryptContext = \
envelopeInfoPtr->iExtraCertChain = CRYPT_ERROR;
envelopeInfoPtr->iSigCheckKeyset = envelopeInfoPtr->iEncryptionKeyset = \
envelopeInfoPtr->iDecryptionKeyset = CRYPT_ERROR;
envelopeInfoPtr->payloadSize = CRYPT_UNUSED;
/* Set up the enveloping methods */
if( isDeenvelope )
{
/* For de-enveloping we default to PKCS #7/CMS/SMIME, if the data
is in some other format we'll adjust the function pointers once
the user pushes in the first data quantity */
initCMSDeenveloping( envelopeInfoPtr );
initDeenvelopeStreaming( envelopeInfoPtr );
initDenvResourceHandling( envelopeInfoPtr );
}
else
{
if( formatType == CRYPT_FORMAT_PGP )
initPGPEnveloping( envelopeInfoPtr );
else
initCMSEnveloping( envelopeInfoPtr );
initEnvelopeStreaming( envelopeInfoPtr );
initEnvResourceHandling( envelopeInfoPtr );
}
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createEnvelope( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue )
{
CRYPT_ENVELOPE iCryptEnvelope;
ENVELOPE_INFO *envelopeInfoPtr = NULL;
int initStatus, status;
assert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );
REQUIRES( auxDataPtr == NULL && auxValue == 0 );
REQUIRES( createInfo->arg1 > CRYPT_FORMAT_NONE && \
createInfo->arg1 < CRYPT_FORMAT_LAST_EXTERNAL );
/* Pass the call on to the lower-level open function */
initStatus = initEnvelope( &iCryptEnvelope, createInfo->cryptOwner,
createInfo->arg1, &envelopeInfoPtr );
if( cryptStatusError( initStatus ) )
{
/* If the create object failed, return immediately */
if( envelopeInfoPtr == NULL )
return( initStatus );
/* The init failed, make sure that the object gets destroyed when we
notify the kernel that the setup process is complete */
krnlSendNotifier( iCryptEnvelope, IMESSAGE_DESTROY );
}
/* We've finished setting up the object-type-specific info, tell the
kernel that the object is ready for use */
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
return( cryptStatusError( initStatus ) ? initStatus : status );
createInfo->cryptHandle = iCryptEnvelope;
return( CRYPT_OK );
}
#endif /* USE_ENVELOPES */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -