📄 res_denv.c
字号:
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
sMemDisconnect( &stream );
return( status );
}
/* Perform additional checks beyond those performed for a standard
signature as required by CMS signatures */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int checkCmsSignatureInfo( INOUT CONTENT_LIST *contentListPtr,
IN_HANDLE const CRYPT_HANDLE iHashContext,
IN_HANDLE const CRYPT_HANDLE iSigCheckContext,
IN_ENUM( CRYPT_CONTENT ) \
const CRYPT_CONTENT_TYPE contentType,
INOUT ERROR_INFO *errorInfo )
{
CONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;
int status;
assert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
assert( isWritePtr( errorInfo, sizeof( ENVELOPE_INFO ) ) );
REQUIRES( isHandleRangeValid( iHashContext ) );
REQUIRES( isHandleRangeValid( iSigCheckContext ) );
REQUIRES( contentType > CRYPT_CONTENT_NONE && \
contentType < CRYPT_CONTENT_LAST );
/* If it's CMS signed data then the signature check key should be
included with the signed data as a certificate chain, however it's
possible (though unlikely) that the certificates may be unrelated to
the signature, in which case the caller will have provided the
signature check key from an external source */
status = iCryptCheckSignature( contentListPtr->object,
contentListPtr->objectSize,
CRYPT_FORMAT_CMS,
( sigInfo->iSigCheckKey == CRYPT_ERROR ) ? \
iSigCheckContext : sigInfo->iSigCheckKey,
iHashContext, CRYPT_UNUSED,
&sigInfo->iExtraData );
if( cryptStatusError( status ) )
{
retExt( CRYPT_ERROR_SIGNATURE,
( CRYPT_ERROR_SIGNATURE, errorInfo,
"Signature verification failed" ) );
}
/* If there are authenticated attributes present we have to perform an
extra check to make sure that the content-type specified in the
authenticated attributes matches the actual data content type */
if( sigInfo->iExtraData != CRYPT_ERROR )
{
int signatureContentType;
status = krnlSendMessage( sigInfo->iExtraData, IMESSAGE_GETATTRIBUTE,
&signatureContentType,
CRYPT_CERTINFO_CMS_CONTENTTYPE );
if( cryptStatusError( status ) || \
signatureContentType != contentType )
{
retExt( CRYPT_ERROR_SIGNATURE,
( CRYPT_ERROR_SIGNATURE, errorInfo,
"Content-type in authenticated attributes doesn't "
"match actual content type" ) );
}
}
/* If there are unauthenticated attributes present, process them. We
don't record the processing status for these to ensure that some
random error in the non signature-related attributes doesn't
invalidate an otherwise OK signature */
if( sigInfo->extraData2 != NULL )
{
const int localStatus = \
processUnauthAttributes( contentListPtr, sigInfo->extraData2,
sigInfo->extraData2Length );
if( cryptStatusError( localStatus ) )
{
retExt( CRYPT_ERROR_BADDATA,
( CRYPT_ERROR_BADDATA, errorInfo,
"Invalid unauthenticated attribute data") );
}
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Process Encryption Data *
* *
****************************************************************************/
/* Import a wrapped session key */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int importSessionKey( const CONTENT_LIST *contentListPtr,
IN_HANDLE const CRYPT_CONTEXT iImportContext,
OUT_HANDLE_OPT CRYPT_CONTEXT *iSessionKeyContext )
{
CRYPT_CONTEXT iSessionKey;
const CONTENT_LIST *sessionKeyInfoPtr;
MESSAGE_CREATEOBJECT_INFO createInfo;
int iterationCount, status;
assert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
assert( isWritePtr( iSessionKeyContext, sizeof( CRYPT_CONTEXT ) ) );
REQUIRES( isHandleRangeValid( iImportContext ) );
/* Clear return value */
*iSessionKeyContext = CRYPT_ERROR;
#ifdef USE_PGP
/* PGP doesn't provide separate session key information with the
encrypted data but wraps it up alongside the encrypted key so we
can't import the wrapped key into a context via the standard key
import functions but instead have to create the context as part of
the unwrap process */
if( contentListPtr->formatType == CRYPT_FORMAT_PGP )
{
return( iCryptImportKey( contentListPtr->object,
contentListPtr->objectSize,
CRYPT_FORMAT_PGP, iImportContext,
CRYPT_UNUSED, iSessionKeyContext ) );
}
#endif /* USE_PGP */
/* Look for the information required to recreate the session key context */
for( sessionKeyInfoPtr = contentListPtr, iterationCount = 0;
sessionKeyInfoPtr != NULL && \
sessionKeyInfoPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
sessionKeyInfoPtr = sessionKeyInfoPtr->next, iterationCount++ );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
if( sessionKeyInfoPtr == NULL )
{
/* We need to read more data before we can recreate the session key */
return( CRYPT_ERROR_UNDERFLOW );
}
/* Create the session key context and import the encrypted session key */
setMessageCreateObjectInfo( &createInfo,
sessionKeyInfoPtr->clEncrInfo.cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
iSessionKey = createInfo.cryptHandle;
status = krnlSendMessage( iSessionKey, IMESSAGE_SETATTRIBUTE,
( void * ) &sessionKeyInfoPtr->clEncrInfo.cryptMode,
CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) )
{
status = iCryptImportKey( contentListPtr->object,
contentListPtr->objectSize,
contentListPtr->formatType, iImportContext,
iSessionKey, NULL );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );
return( status );
}
*iSessionKeyContext = iSessionKey;
return( CRYPT_OK );
}
/* Set up the envelope decryption using an added or recovered session key */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int initSessionKeyDecryption( INOUT ENVELOPE_INFO *envelopeInfoPtr,
IN_HANDLE \
const CRYPT_CONTEXT iSessionKeyContext,
const BOOLEAN isRecoveredSessionKey )
{
ACTION_RESULT actionResult;
int status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
REQUIRES( isHandleRangeValid( iSessionKeyContext ) );
/* If we recovered the session key from a key exchange action rather
than having it passed directly to us by the user, try and set up the
decryption */
if( isRecoveredSessionKey )
{
const CONTENT_LIST *contentListPtr;
int iterationCount;
/* If we got as far as the encrypted data (indicated by the fact
that there's content info present) we can set up the decryption.
If we didn't get this far it'll be set up by the de-enveloping
code when we reach it */
for( contentListPtr = envelopeInfoPtr->contentList, iterationCount = 0;
contentListPtr != NULL && \
contentListPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
contentListPtr = contentListPtr->next, iterationCount++ );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
if( contentListPtr != NULL )
{
const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;
/* We've got to the encrypted data, set up the decryption */
status = initEnvelopeEncryption( envelopeInfoPtr,
iSessionKeyContext, encrInfo->cryptAlgo,
encrInfo->cryptMode, encrInfo->saltOrIV,
encrInfo->saltOrIVsize, FALSE );
if( cryptStatusError( status ) )
return( status );
}
}
/* Add the recovered session encryption action to the action list */
actionResult = checkAction( envelopeInfoPtr->actionList, ACTION_CRYPT,
iSessionKeyContext );
if( actionResult == ACTION_RESULT_ERROR || \
actionResult == ACTION_RESULT_INITED )
return( CRYPT_ERROR_INITED );
status = addAction( &envelopeInfoPtr->actionList,
envelopeInfoPtr->memPoolState, ACTION_CRYPT,
iSessionKeyContext );
if( cryptStatusError( status ) )
return( status );
/* Notify the kernel that the session key context is attached to the
envelope. This is an internal object used only by the envelope so we
tell the kernel not to increment its reference count when it attaches
it */
return( krnlSendMessage( envelopeInfoPtr->objectHandle,
IMESSAGE_SETDEPENDENT,
( void * ) &iSessionKeyContext,
SETDEP_OPTION_NOINCREF ) );
}
/****************************************************************************
* *
* Add De-enveloping Information *
* *
****************************************************************************/
/* Add signature verification information */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int findHashActionFunction( const ACTION_LIST *actionListPtr,
IN_INT_Z const int hashAlgo )
{
CRYPT_ALGO_TYPE actionCryptAlgo;
int status;
assert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );
REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
hashAlgo <= CRYPT_ALGO_LAST_HASH );
/* Check to see if it's the action that we want */
status = krnlSendMessage( actionListPtr->iCryptHandle,
IMESSAGE_GETATTRIBUTE, &actionCryptAlgo,
CRYPT_CTXINFO_ALGO );
return( ( actionCryptAlgo == hashAlgo ) ? CRYPT_OK : CRYPT_ERROR );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int addSignatureInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
INOUT CONTENT_LIST *contentListPtr,
IN_HANDLE const CRYPT_HANDLE sigCheckContext,
const BOOLEAN isExternalKey )
{
CONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;
ACTION_LIST *actionListPtr;
int status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
REQUIRES( isHandleRangeValid( sigCheckContext ) );
/* If we've already processed this entry, return the cached processing
result */
if( contentListPtr->flags & CONTENTLIST_PROCESSED )
return( sigInfo->processingResult );
/* Find the hash action that we need to check this signature. If we
can't find one, return a bad signature error since something must
have altered the algorithm ID for the hash */
actionListPtr = findActionIndirect( envelopeInfoPtr->actionList,
findHashActionFunction,
sigInfo->hashAlgo );
if( actionListPtr == NULL || actionListPtr->action != ACTION_HASH )
{
contentListPtr->flags |= CONTENTLIST_PROCESSED;
sigInfo->processingResult = CRYPT_ERROR_SIGNATURE;
retExt( CRYPT_ERROR_SIGNATURE,
( CRYPT_ERROR_SIGNATURE, ENVELOPE_ERRINFO,
"Signature hash algorithm doesn't match hash algorithm "
"applied to enveloped data" ) );
}
/* Check the signature */
if( contentListPtr->formatType == CRYPT_FORMAT_CMS )
{
status = checkCmsSignatureInfo( contentListPtr,
actionListPtr->iCryptHandle,
sigCheckContext,
envelopeInfoPtr->contentType,
ENVELOPE_ERRINFO );
}
else
{
status = iCryptCheckSignature( contentListPtr->object,
contentListPtr->objectSize,
contentListPtr->formatType, sigCheckContext,
actionListPtr->iCryptHandle, CRYPT_UNUSED,
NULL );
if( cryptStatusError( status ) )
{
setErrorString( ENVELOPE_ERRINFO,
"Signature verification failed", 29 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -