📄 denv_cms.c
字号:
envelopeInfoPtr->flags |= ENVELOPE_ZSTREAMINITED;
else
status = CRYPT_ERROR_MEMORY;
#else
status = CRYPT_ERROR_NOTAVAIL;
#endif /* USE_COMPRESSION */
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( status );
}
state = DEENVSTATE_CONTENT;
break;
case ACTION_NONE:
/* Since we go straight to the data payload there's no nested
content type, so we explicitly set it to data */
envelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;
state = DEENVSTATE_DATA;
break;
default:
assert( NOTREACHED );
}
/* Remember how far we got */
streamPos = stell( &stream );
}
/* Keep consuming information until we run out of input or reach the data
payload */
while( state != DEENVSTATE_DONE )
{
/* Check that various values are within range. They can go out of
range if the header is corrupted */
if( envelopeInfoPtr->hdrSetLength < 0 && \
envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )
{
status = CRYPT_ERROR_BADDATA;
break;
}
/* Read the start of the cert set from a keyAgreement's [0] IMPLICIT
SEQUENCE { [0] SET OF Certificate } */
if( state == DEENVSTATE_SET_ENCR )
{
/* Read the SET tag and length */
status = readSetI( &stream, &length );
if( cryptStatusError( status ) )
break;
/* Remember where we are and move on to the next state. Some
implementations use the indefinite-length encoding for this so
if there's no length given we have to look for the EOC after
each entry read */
streamPos = stell( &stream );
envelopeInfoPtr->hdrSetLength = length;
state = DEENVSTATE_ENCR;
}
/* Read and remember a key exchange object from an EncryptionKeyInfo
record */
if( state == DEENVSTATE_ENCR )
{
/* Add the object to the content information list */
status = addContentListItem( &stream, envelopeInfoPtr, NULL );
if( cryptStatusError( status ) )
break;
/* Remember where we are and move on to the next state if
necessary */
streamPos = stell( &stream );
if( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )
{
envelopeInfoPtr->hdrSetLength -= status;
if( envelopeInfoPtr->hdrSetLength <= 0 )
state = DEENVSTATE_ENCRCONTENT;
}
else
{
status = checkEOC( &stream );
if( cryptStatusError( status ) )
break;
if( status == TRUE )
state = DEENVSTATE_ENCRCONTENT;
}
}
/* Read the encrypted content information */
if( state == DEENVSTATE_ENCRCONTENT )
{
QUERY_INFO queryInfo;
/* Read the encrypted content header */
status = readCMSencrHeader( &stream, nestedContentOIDselection,
NULL, &queryInfo );
if( cryptStatusError( status ) )
break;
envelopeInfoPtr->contentType = status;
envelopeInfoPtr->payloadSize = queryInfo.size;
/* We've reached encrypted data, we can't go any further until we
can either recover the session key from a key exchange object
or are fed the session key directly */
if( envelopeInfoPtr->actionList == NULL )
{
/* Since the content can be indefinite-length, we clear the
size field to give it a sensible setting */
queryInfo.size = 0;
status = addContentListItem( &stream, envelopeInfoPtr,
&queryInfo );
}
else
{
assert( envelopeInfoPtr->actionList->action == ACTION_CRYPT );
/* If the session key was recovered from a key exchange
action but we ran out of input data before we could read
the encryptedContent info, it'll be present in the action
list so we use it to set things up for the decryption.
This can only happen if the caller pushes in just enough
data to get past the key exchange actions but not enough
to recover the encryptedContent info and then pushes in a
key exchange action in response to the
CRYPT_ERROR_UNDERFLOW error */
status = initEnvelopeEncryption( envelopeInfoPtr,
envelopeInfoPtr->actionList->iCryptHandle,
queryInfo.cryptMode, queryInfo.cryptMode,
queryInfo.iv, queryInfo.ivLength,
FALSE );
}
if( cryptStatusError( status ) )
break;
/* Remember where we are and move on to the next state */
streamPos = stell( &stream );
state = DEENVSTATE_DATA;
if( envelopeInfoPtr->actionList == NULL )
{
/* If we haven't got a session key to decrypt the data that
follows, we can't go beyond this point */
status = CRYPT_ENVELOPE_RESOURCE;
break;
}
}
/* Read the start of the SET OF DigestAlgorithmIdentifier */
if( state == DEENVSTATE_SET_HASH )
{
/* Read the SET tag and length */
status = readSetI( &stream, &length );
if( cryptStatusError( status ) )
break;
/* Remember where we are and move on to the next state. Some
implementations use the indefinite-length encoding for this so
if there's no length given we have to look for the EOC after
each entry read */
streamPos = stell( &stream );
envelopeInfoPtr->hdrSetLength = length;
state = DEENVSTATE_HASH;
}
/* Read and remember a hash object from a DigestAlgorithmIdentifier
record */
if( state == DEENVSTATE_HASH )
{
CRYPT_ALGO_TYPE hashAlgo;
CRYPT_CONTEXT iHashContext;
ACTION_LIST *actionListPtr;
/* Create the hash object from the data */
status = readContextAlgoID( &stream, &iHashContext, NULL,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
&hashAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
break;
/* Check whether an identical hash action is already present,
either through being supplied externally or from a duplicate
entry in the set */
for( actionListPtr = envelopeInfoPtr->actionList;
actionListPtr != NULL; actionListPtr = actionListPtr->next )
{
CRYPT_ALGO_TYPE actionHashAlgo;
status = krnlSendMessage( actionListPtr->iCryptHandle,
IMESSAGE_GETATTRIBUTE,
&actionHashAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) && actionHashAlgo == hashAlgo )
{
/* There's a duplicate action present, destroy the one
we've just created and exit */
krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
break;
}
}
if( actionListPtr == NULL )
{
/* We didn't find any duplicates, append the new hash action
to the action list and remember that hashing is now
active */
if( addAction( &envelopeInfoPtr->actionList,
envelopeInfoPtr->memPoolState, ACTION_HASH,
iHashContext ) == NULL )
{
status = CRYPT_ERROR_MEMORY;
break;
}
envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;
}
assert( envelopeInfoPtr->actionList->action == ACTION_HASH );
/* Remember where we are and move on to the next state if
necessary */
if( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )
{
envelopeInfoPtr->hdrSetLength -= stell( &stream ) - streamPos;
streamPos = stell( &stream );
if( envelopeInfoPtr->hdrSetLength <= 0 )
state = DEENVSTATE_CONTENT;
}
else
{
status = checkEOC( &stream );
if( cryptStatusError( status ) )
break;
if( status == TRUE )
state = DEENVSTATE_CONTENT;
}
}
/* Read the encapsulated content header */
if( state == DEENVSTATE_CONTENT )
{
status = readCMSheader( &stream, nestedContentOIDselection,
&envelopeInfoPtr->payloadSize, TRUE );
if( cryptStatusError( status ) )
break;
envelopeInfoPtr->contentType = status;
status = CRYPT_OK;
/* If there's no content included and it's not an attributes-only
message, this is a detached signature with the content supplied
anderswhere */
if( !envelopeInfoPtr->payloadSize && \
!( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY ) )
envelopeInfoPtr->flags |= ENVELOPE_DETACHED_SIG;
/* Remember where we are and move on to the next state */
streamPos = stell( &stream );
state = ( envelopeInfoPtr->payloadSize == 0 && \
( envelopeInfoPtr->flags & ( ENVELOPE_DETACHED_SIG | \
ENVELOPE_ATTRONLY ) ) ) ? \
DEENVSTATE_DONE : DEENVSTATE_DATA;
}
/* Start the decryption process if necessary */
if( state == DEENVSTATE_DATA )
{
/* Synchronise the data stream processing to the start of the
encrypted data and move back to the start of the data
stream */
status = envelopeInfoPtr->syncDeenvelopeData( envelopeInfoPtr,
&stream );
if( cryptStatusError( status ) )
break;
streamPos = 0;
/* We're done */
state = DEENVSTATE_DONE;
assert( actionsOK( envelopeInfoPtr ) );
}
}
envelopeInfoPtr->deenvState = state;
assert( streamPos >= 0 && envelopeInfoPtr->bufPos - streamPos >= 0 );
/* Consume the input we've processed so far by moving everything past the
current position down to the start of the memory buffer */
length = envelopeInfoPtr->bufPos - streamPos;
if( length > 0 && streamPos > 0 )
memmove( envelopeInfoPtr->buffer, envelopeInfoPtr->buffer + streamPos,
length );
envelopeInfoPtr->bufPos = length;
/* If all went OK but we're still not out of the header information,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -