📄 res_denv.c
字号:
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int completeEnvelopeInfoUpdate( INOUT ENVELOPE_INFO *envelopeInfoPtr )
{
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
/* Destroy the content list, which at this point will contain only (now-
irrelevant) key exchange items */
deleteContentList( envelopeInfoPtr->memPoolState,
&envelopeInfoPtr->contentList );
envelopeInfoPtr->contentList = envelopeInfoPtr->contentListCurrent = NULL;
/* If the only error was an information required error, we've now
resolved the problem and can continue */
if( envelopeInfoPtr->errorState == CRYPT_ENVELOPE_RESOURCE )
{
envelopeInfoPtr->errorState = CRYPT_OK;
/* The envelope is ready to process data, move it into the high
state. Normally this is handled in the data-push code but this
leads to a race condition when all the data being pushed is
buffered inside the envelope, requiring only that processing be
enabled by adding a resource. Once the resource is added the
only action left for the caller to perform is a flush, so they
expect that high-state actions should succeed even though the
envelope state machine wouldn't move the envelope into the high
state until some data action (in this case a flush) is
initiated. To avoid this problem we move the envelope into the
high state as soon as the resource blockage has been cleared,
since any high-state-only information (for example the nested
content type) will now be available */
return( krnlSendMessage( envelopeInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,
CRYPT_IATTRIBUTE_INITIALISED ) );
}
return( CRYPT_OK );
}
/* Add de-enveloping information to an envelope */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int addDeenvelopeInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE envInfo,
IN_INT_Z const int value )
{
CRYPT_HANDLE cryptHandle = ( CRYPT_HANDLE ) value;
CRYPT_CONTEXT iNewContext = DUMMY_INIT;
CRYPT_ATTRIBUTE_TYPE localEnvInfo = envInfo;
CONTENT_LIST *contentListPtr;
BOOLEAN isExternalKey = TRUE;
int status = CRYPT_OK;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
REQUIRES( envInfo == CRYPT_IATTRIBUTE_ATTRONLY || \
( envInfo > CRYPT_ENVINFO_FIRST && \
envInfo < CRYPT_ENVINFO_LAST ) );
/* A signature-check object can be passed in as a special-case type
CRYPT_ENVINFO_SIGNATURE_RESULT to indicate that the object was
obtained internally (for example by instantiating it from an attached
certificate chain) and doesn't require various special-case
operations that are applied to user-supplied objects. If this is the
case we convert it to a standard CRYPT_ENVINFO_SIGNATURE and remember
that it's an internally-supplied key */
if( envInfo == CRYPT_ENVINFO_SIGNATURE_RESULT )
{
localEnvInfo = CRYPT_ENVINFO_SIGNATURE;
isExternalKey = FALSE;
}
/* Since we can add one of a multitude of necessary information types
we need to check to make sure that what we're adding is appropriate.
We do this by trying to match what's being added to the first
information object of the correct type */
status = matchInfoObject( &contentListPtr, envelopeInfoPtr,
localEnvInfo );
if( cryptStatusError( status ) )
{
retExtArg( status,
( status, ENVELOPE_ERRINFO,
"Added item doesn't match %s envelope information "
"object",
( envelopeInfoPtr->contentListCurrent != NULL ) ? \
"currently selected" : "any" ) );
}
/* Process non-encryption-related enveloping info */
switch( localEnvInfo )
{
case CRYPT_IATTRIBUTE_ATTRONLY:
/* This is off by default so we should only be turning it on */
REQUIRES( value == TRUE );
envelopeInfoPtr->flags |= ENVELOPE_ATTRONLY;
return( CRYPT_OK );
case CRYPT_ENVINFO_KEYSET_SIGCHECK:
case CRYPT_ENVINFO_KEYSET_ENCRYPT:
case CRYPT_ENVINFO_KEYSET_DECRYPT:
/* It's keyset information, keep a record of it for later use */
return( addKeysetInfo( envelopeInfoPtr, localEnvInfo,
cryptHandle ) );
case CRYPT_ENVINFO_HASH:
{
ACTION_LIST *actionListItem;
/* The user is checking a detached signature, remember the hash
for later. In theory we should also check the state of the
hash context, however PGP requires that it not be completed
(since it needs to hash further data) and everything else
requires that it be completed, but we don't know at this
point whether we're processing PGP or non-PGP data so we
can't perform any checking here */
if( envelopeInfoPtr->actionList != NULL )
{
/* There's already a hash action present, we can't add
anything further */
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_HASH,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Make sure that we can still add another action */
if( !moreActionsPossible( envelopeInfoPtr->actionList ) )
return( CRYPT_ERROR_OVERFLOW );
/* Add the hash as an action list item */
status = addActionEx( &actionListItem,
&envelopeInfoPtr->actionList,
envelopeInfoPtr->memPoolState,
ACTION_HASH, cryptHandle );
if( cryptStatusError( status ) )
return( status );
return( krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT ) );
}
case CRYPT_ENVINFO_SIGNATURE:
/* It's a signature object, check the signature and exit */
return( addSignatureInfo( envelopeInfoPtr, contentListPtr,
cryptHandle, isExternalKey ) );
}
/* Make sure that we can still add another action */
if( !moreActionsPossible( envelopeInfoPtr->actionList ) )
return( CRYPT_ERROR_OVERFLOW );
/* Anything that's left at this point related to envelope decryption */
switch( localEnvInfo )
{
case CRYPT_ENVINFO_PRIVATEKEY:
case CRYPT_ENVINFO_KEY:
/* Import the session key using the KEK */
status = importSessionKey( contentListPtr, cryptHandle,
&iNewContext );
break;
case CRYPT_ENVINFO_SESSIONKEY:
{
/* If we've been given the session key directly then we must
have reached the encrypted data so we take a copy and set
up the decryption with it */
const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;
status = initEnvelopeEncryption( envelopeInfoPtr, cryptHandle,
encrInfo->cryptAlgo, encrInfo->cryptMode,
encrInfo->saltOrIV, encrInfo->saltOrIVsize, TRUE );
if( cryptStatusOK( status ) )
{
/* The session key context is the newly-created internal
one */
iNewContext = envelopeInfoPtr->iCryptContext;
}
break;
}
default:
retIntError();
}
if( cryptStatusError( status ) )
return( status );
/* We've now got the session key, if we recovered it from a key exchange
action (rather than having it passed directly to us by the user) try
and set up the decryption */
if( envelopeInfoPtr->usage != ACTION_MAC )
{
status = initSessionKeyDecryption( envelopeInfoPtr, iNewContext,
( localEnvInfo != CRYPT_ENVINFO_SESSIONKEY ) ? \
TRUE : FALSE );
if( cryptStatusError( status ) )
{
if( localEnvInfo != CRYPT_ENVINFO_SESSIONKEY )
krnlSendNotifier( iNewContext, IMESSAGE_DECREFCOUNT );
if( status == CRYPT_ERROR_INITED )
{
/* If the attribute that we added to recover the session key
is already present, provide extended error information */
setErrorInfo( envelopeInfoPtr, localEnvInfo,
CRYPT_ERRTYPE_ATTR_PRESENT );
}
return( status );
}
}
/* Complete the envelope information update */
return( completeEnvelopeInfoUpdate( envelopeInfoPtr ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int addDeenvelopeInfoString( INOUT ENVELOPE_INFO *envelopeInfoPtr,
IN_RANGE( CRYPT_ENVINFO_PASSWORD, \
CRYPT_ENVINFO_PASSWORD ) \
const CRYPT_ATTRIBUTE_TYPE envInfo,
IN_BUFFER( valueLength ) const void *value,
IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
const int valueLength )
{
CRYPT_CONTEXT iNewContext = DUMMY_INIT;
CONTENT_LIST *contentListPtr;
int status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( isReadPtr( value, valueLength ) );
REQUIRES( envInfo == CRYPT_ENVINFO_PASSWORD );
REQUIRES( valueLength > 0 && valueLength < MAX_ATTRIBUTE_SIZE );
/* Since we can add one of a multitude of necessary information types,
we need to check to make sure that what we're adding is appropriate.
We do this by trying to match what's being added to the first
information object of the correct type */
status = matchInfoObject( &contentListPtr, envelopeInfoPtr, envInfo );
if( cryptStatusError( status ) )
{
retExt( status,
( status, ENVELOPE_ERRINFO,
"Added item doesn't match any envelope information "
"object" ) );
}
/* If we've been given a password and we need private key information,
it's the password required to decrypt the key so we treat this
specially. This action recursively calls addDeenvelopeInfo() with
the processed private key so we don't have to fall through to the
session-key processing code below like the other key-handling
actions */
if( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY )
{
return( addPrivkeyPasswordInfo( envelopeInfoPtr, contentListPtr,
value, valueLength ) );
}
/* Make sure that we can still add another action */
if( envelopeInfoPtr->usage != ACTION_MAC && \
!moreActionsPossible( envelopeInfoPtr->actionList ) )
return( CRYPT_ERROR_OVERFLOW );
/* We've been given a standard decryption password, create a decryption
context for it, derive the key from the password, and use it to
import the session/MAC key */
if( envelopeInfoPtr->usage == ACTION_MAC )
{
if( envelopeInfoPtr->actionList == NULL )
return( CRYPT_ERROR_NOTINITED );
status = addPasswordInfo( contentListPtr, value, valueLength,
envelopeInfoPtr->actionList->iCryptHandle,
NULL, envelopeInfoPtr->type,
ENVELOPE_ERRINFO );
}
else
{
status = addPasswordInfo( contentListPtr, value, valueLength,
CRYPT_UNUSED, &iNewContext,
envelopeInfoPtr->type, ENVELOPE_ERRINFO );
}
if( cryptStatusError( status ) )
return( status );
/* We've recovered the session key, try and set up the decryption */
if( envelopeInfoPtr->usage != ACTION_MAC )
{
status = initSessionKeyDecryption( envelopeInfoPtr, iNewContext,
TRUE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iNewContext, IMESSAGE_DECREFCOUNT );
if( status == CRYPT_ERROR_INITED )
{
/* If the attribute that we added to recover the session key
is already present, provide extended error information */
setErrorInfo( envelopeInfoPtr, envInfo,
CRYPT_ERRTYPE_ATTR_PRESENT );
}
return( status );
}
}
/* Complete the envelope information update */
return( completeEnvelopeInfoUpdate( envelopeInfoPtr ) );
}
/****************************************************************************
* *
* Envelope Access Routines *
* *
****************************************************************************/
STDC_NONNULL_ARG( ( 1 ) ) \
void initDenvResourceHandling( INOUT ENVELOPE_INFO *envelopeInfoPtr )
{
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
REQUIRES_V( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE );
/* Set the access method pointers */
envelopeInfoPtr->addInfo = addDeenvelopeInfo;
envelopeInfoPtr->addInfoString = addDeenvelopeInfoString;
}
#endif /* USE_ENVELOPES */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -