📄 resource.c
字号:
encrInfo->saltOrIV : NULL,
encrInfo->keySetupIterations );
else
#endif /* USE_PGP */
{
RESOURCE_DATA msgData;
/* Load the derivation information into the context */
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE,
( void * ) &encrInfo->keySetupIterations,
CRYPT_CTXINFO_KEYING_ITERATIONS );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) encrInfo->saltOrIV,
encrInfo->saltOrIVsize );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) value, valueLength );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_VALUE );
}
}
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Recover the session key using the password context and destroy it
when we're done with it */
if( envelopeInfoPtr->type != CRYPT_FORMAT_PGP )
{
status = importSessionKey( envelopeInfoPtr, contentListPtr,
createInfo.cryptHandle, &iNewContext );
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
return( status );
}
else
/* In PGP there isn't any encrypted session key, so the context
created from the password becomes the bulk encryption
context */
iNewContext = createInfo.cryptHandle;
}
/* If we've been given a KEK (symmetric or asymmetric), recreate the
session key by importing it using the KEK */
if( envInfo == CRYPT_ENVINFO_PRIVATEKEY || \
envInfo == CRYPT_ENVINFO_KEY )
{
/* Import the session key using the KEK */
status = importSessionKey( envelopeInfoPtr, contentListPtr,
cryptHandle, &iNewContext );
if( cryptStatusError( status ) )
return( status );
}
/* At this point we have the session key, either by recovering it from a
key exchange action or by having it passed to us directly. If we've
been given it directly then we must have reached the encrypted data
so we take a copy and set up the decryption with it */
if( envInfo == CRYPT_ENVINFO_SESSIONKEY )
{
const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;
status = initEnvelopeEncryption( envelopeInfoPtr, cryptHandle,
encrInfo->cryptAlgo, encrInfo->cryptMode,
encrInfo->saltOrIV, encrInfo->saltOrIVsize, TRUE );
if( cryptStatusError( status ) )
return( status );
/* The session key context is the newly-created internal one */
iNewContext = envelopeInfoPtr->iCryptContext;
}
else
{
/* We've recovered the session key from a key exchange action. If
we got as far as the encrypted data (indicated by the fact that
there's content info present), we set up the decryption. If we
didn't get this far, it'll be set up by the deenveloping code
when we reach it */
for( contentListPtr = envelopeInfoPtr->contentList;
contentListPtr != NULL && \
contentListPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY;
contentListPtr = contentListPtr->next );
if( contentListPtr != NULL )
{
const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;
/* We got to the encrypted data, set up the decryption */
status = initEnvelopeEncryption( envelopeInfoPtr, iNewContext,
encrInfo->cryptAlgo, encrInfo->cryptMode,
encrInfo->saltOrIV, encrInfo->saltOrIVsize, FALSE );
if( cryptStatusError( status ) )
return( status );
}
}
/* Add the recovered session encryption action to the action list */
if( checkAction( envelopeInfoPtr->actionList, ACTION_CRYPT,
iNewContext ) == ACTION_RESULT_INITED )
return( CRYPT_ERROR_INITED );
if( addAction( &envelopeInfoPtr->actionList,
envelopeInfoPtr->memPoolState, ACTION_CRYPT,
iNewContext ) == NULL )
return( CRYPT_ERROR_MEMORY );
/* 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 */
krnlSendMessage( envelopeInfoPtr->objectHandle, IMESSAGE_SETDEPENDENT,
&iNewContext, SETDEP_OPTION_NOINCREF );
/* 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;
return( status );
}
/****************************************************************************
* *
* Enveloping Information Management Functions *
* *
****************************************************************************/
#ifdef USE_FORTEZZA
/* Check that an object being added is suitable for use with Fortezza data */
static int checkFortezzaUsage( const CRYPT_HANDLE cryptHandle,
const ENVELOPE_INFO *envelopeInfoPtr,
const CRYPT_ATTRIBUTE_TYPE envInfo )
{
CRYPT_ALGO_TYPE cryptAlgo;
int device1, device2, status;
/* Make sure that the new session key being added (if there's existing
originator info) or the existing one (if it's originator info being
added) is a Skipjack context */
status = krnlSendMessage( ( envInfo == CRYPT_ENVINFO_ORIGINATOR ) ? \
envelopeInfoPtr->iCryptContext : cryptHandle,
IMESSAGE_GETATTRIBUTE, &cryptAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) || cryptAlgo != CRYPT_ALGO_SKIPJACK )
return( CRYPT_ARGERROR_NUM1 );
/* Make sure that both objects are present in the same device */
status = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT, &device1,
OBJECT_TYPE_DEVICE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( envelopeInfoPtr->iCryptContext,
IMESSAGE_GETDEPENDENT, &device2,
OBJECT_TYPE_DEVICE );
if( cryptStatusOK( status ) && ( device1 != device2 ) )
status = CRYPT_ARGERROR_NUM1;
return( status );
}
#endif /* USE_FORTEZZA */
/* Add enveloping information to an envelope */
static int addEnvelopeInfo( ENVELOPE_INFO *envelopeInfoPtr,
const CRYPT_ATTRIBUTE_TYPE envInfo,
const void *value, const int valueLength )
{
CRYPT_HANDLE cryptHandle = *( CRYPT_HANDLE * ) value;
ACTION_LIST *actionListPtr, **actionListHeadPtrPtr, *hashActionPtr;
ACTION_RESULT actionResult;
ACTION_TYPE actionType;
int status;
/* If it's meta-information, remember the value */
if( envInfo == CRYPT_ENVINFO_DATASIZE )
{
envelopeInfoPtr->payloadSize = *( int * ) value;
return( CRYPT_OK );
}
if( envInfo == CRYPT_ENVINFO_CONTENTTYPE )
{
envelopeInfoPtr->contentType = *( int * ) value;
return( CRYPT_OK );
}
if( envInfo == CRYPT_ENVINFO_DETACHEDSIGNATURE || \
envInfo == CRYPT_ENVINFO_MAC )
{
/* Turn a generic zero/nonzero boolean into TRUE or FALSE */
const BOOLEAN flag = ( *( int * ) value ) ? TRUE : FALSE;
if( envInfo == CRYPT_ENVINFO_DETACHEDSIGNATURE )
{
if( flag )
{
if( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY )
/* Detached-sig and attribute-only messages are mutually
exclusive */
return( CRYPT_ERROR_INITED );
envelopeInfoPtr->flags |= ENVELOPE_DETACHED_SIG;
}
else
envelopeInfoPtr->flags &= ~ENVELOPE_DETACHED_SIG;
}
else
{
/* The MAC flag is somewhat different from the detached-signature
one in that the latter is a modifier for an existing envelope
usage while the former changes the usage itself. Because of
this it can only be set to TRUE (if it could be reset the
caller could set non-MAC-compatible options by clearing the
flag and then setting it again afterwards), since the envelope
usage change occurs at a higher level all we do here is make
sure that the flag isn't being cleared */
if( !flag )
return( CRYPT_ARGERROR_NUM1 );
/* There are no known implementations of this content-type, so
for now we disallow any attempts to use it */
return( CRYPT_ERROR_NOTAVAIL );
}
return( CRYPT_OK );
}
if( envInfo == CRYPT_IATTRIBUTE_INCLUDESIGCERT )
{
/* This is on by default so we should only be turning it off */
assert( ( *( int * ) value ) == FALSE );
envelopeInfoPtr->flags |= ENVELOPE_NOSIGNINGCERTS;
return( CRYPT_OK );
}
if( envInfo == CRYPT_IATTRIBUTE_ATTRONLY )
{
/* This is off by default so we should only be turning it on */
assert( ( *( int * ) value ) == TRUE );
if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
/* Detached-sig and attribute-only messages are mutually
exclusive */
return( CRYPT_ERROR_INITED );
envelopeInfoPtr->flags |= ENVELOPE_ATTRONLY;
return( CRYPT_OK );
}
/* If it's keyset information, just keep a record of it for later use */
if( envInfo == CRYPT_ENVINFO_KEYSET_SIGCHECK || \
envInfo == CRYPT_ENVINFO_KEYSET_ENCRYPT || \
envInfo == CRYPT_ENVINFO_KEYSET_DECRYPT )
return( addKeyset( envelopeInfoPtr, envInfo, cryptHandle ) );
/* If it's an extra action for the signature, record it with the main
signature action */
if( envInfo == CRYPT_ENVINFO_SIGNATURE_EXTRADATA || \
envInfo == CRYPT_ENVINFO_TIMESTAMP_AUTHORITY )
{
CRYPT_HANDLE *iCryptHandlePtr;
/* Find the last signature action that was added and make sure
that it doesn't already have an action of this type attached to
it */
actionListPtr = envelopeInfoPtr->postActionList;
if( actionListPtr == NULL )
return( CRYPT_ERROR_NOTINITED );
while( actionListPtr->next != NULL && \
actionListPtr->next->action == ACTION_SIGN )
actionListPtr = actionListPtr->next;
iCryptHandlePtr = ( envInfo == CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) ? \
&actionListPtr->iExtraData : \
&actionListPtr->iTspSession;
if( *iCryptHandlePtr != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
/* Increment its reference count and add it to the action */
krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT );
*iCryptHandlePtr = cryptHandle;
return( CRYPT_OK );
}
/* If it's originator information, record it for the enveloped data
header */
if( envInfo == CRYPT_ENVINFO_ORIGINATOR )
{
#ifdef USE_FORTEZZA
/* If there's a session key present, make sure that it's consistent
with the originator info */
if( envelopeInfoPtr->iCryptContext != CRYPT_ERROR )
{
status = checkFortezzaUsage( cryptHandle, envelopeInfoPtr,
CRYPT_ENVINFO_ORIGINATOR );
if( cryptStatusError( status ) )
return( status );
}
/* Increment its reference count and add it to the action */
krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT );
envelopeInfoPtr->iExtraCertChain = cryptHandle;
/* Since we're using Fortezza key management, we have to use Skipjack
as the data encryption algorithm */
envelopeInfoPtr->defaultAlgo = CRYPT_ALGO_SKIPJACK;
return( CRYPT_OK );
#else
return( CRYPT_ARGERROR_NUM1 );
#endif /* USE_FORTEZZA */
}
/* If it's compression information, set up the compression structures */
if( envInfo == CRYPT_ENVINFO_COMPRESSION )
{
#ifdef USE_COMPRESSION
assert( !( envelopeInfoPtr->flags & ENVELOPE_ZSTREAMINITED ) );
/* Initialize the compression */
if( deflateInit( &envelopeInfoPtr->zStream, \
Z_DEFAULT_COMPRESSION ) != Z_OK )
return( CRYPT_ERROR_MEMORY );
envelopeInfoPtr->flags |= ENVELOPE_ZSTREAMINITED;
return( CRYPT_OK );
#else
return( CRYPT_ARGERROR_NUM1 );
#endif /* USE_COMPRESSION */
}
/* If it's a password, derive a session key encryption context from it */
if( envInfo == CRYPT_ENVINFO_PASSWORD )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
CRYPT_ALGO_TYPE cryptAlgo = envelopeInfoPtr->defaultAlgo;
/* PGP doesn't support both PKC and conventional key exchange
actions or multiple conventional key exchange actions in the same
envelope since the session key is encrypted for the PKC action
but derived from the password for the conventional action */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
( findAction( envelopeInfoPtr->preActionList,
ACTION_KEYEXCHANGE_PKC ) != NULL || \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -