📄 resource.c
字号:
envelopeInfoPtr->flags |= ENVELOPE_NOSIGNINGCERTS;
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 extra data for the signature, record it with the signature
action */
if( envInfo == CRYPT_ENVINFO_SIGNATURE_EXTRADATA )
{
/* Find the last signature action which was added and make sure
it doesn't already have extra data 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;
if( actionListPtr->iExtraData != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
/* Increment its reference count and add it to the action */
status = krnlSendNotifier( cryptHandle,
RESOURCE_IMESSAGE_INCREFCOUNT );
if( cryptStatusOK( status ) )
actionListPtr->iExtraData = cryptHandle;
return( status );
}
if( envInfo == CRYPT_ENVINFO_TIMESTAMP_AUTHORITY )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
/* Find the last signature action which was added and make sure
it doesn't already have a TSP session object 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;
if( actionListPtr->iTspSession != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
/* Create the TSP session object necessary for timestamping the
enveloped data */
setMessageCreateObjectInfo( &createInfo, CRYPT_SESSION_TSP );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_SESSION );
if( cryptStatusError( status ) )
return( status );
setResourceData( &msgData, ( void * ) value, valueLength );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_SESSINFO_SERVER_NAME );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
actionListPtr->iTspSession = createInfo.cryptHandle;
return( CRYPT_OK );
}
/* If it's originator information, record it for the enveloped data
header */
if( envInfo == CRYPT_ENVINFO_ORIGINATOR )
{
/* If there's a session key present, make sure 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 */
status = krnlSendNotifier( cryptHandle,
RESOURCE_IMESSAGE_INCREFCOUNT );
if( cryptStatusError( status ) )
return( status );
envelopeInfoPtr->iOriginatorChain = 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 );
}
#ifndef NO_COMPRESSION
/* If it's compression information, set up the compression structures */
if( envInfo == CRYPT_ENVINFO_COMPRESSION )
{
assert( !envelopeInfoPtr->zStreamInited );
/* Initialize the compression */
if( deflateInit( &envelopeInfoPtr->zStream, \
Z_DEFAULT_COMPRESSION ) != Z_OK )
return( CRYPT_ERROR_MEMORY );
envelopeInfoPtr->zStreamInited = TRUE;
return( CRYPT_OK );
}
#endif /* NO_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 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 ) || \
envelopeInfoPtr->actionList != NULL )
return( CRYPT_ERROR_INITED );
/* Create the appropriate encryption context. We have to be careful
to ensure we use an algorithm which is compatible with the
wrapping mechanism. We don't have to perform this check if the
format type is PGP since PGP wrapping always uses CFB mode (so
there are no modes which need to be avoided) and the higher-level
code has constrained the algorithm type to something which is
encodable using the PGP data format */
if( envelopeInfoPtr->type != CRYPT_FORMAT_PGP && \
( isStreamCipher( cryptAlgo ) || \
cryptStatusError( sizeofAlgoIDex( cryptAlgo,
( CRYPT_ALGO ) CRYPT_MODE_CBC, 0 ) ) ) )
cryptAlgo = CRYPT_ALGO_3DES;
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
/* Derive the key into the context and add it to the action list */
#ifndef NO_PGP
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
{
BYTE salt[ PGP_SALTSIZE ];
static const CRYPT_MODE mode = CRYPT_MODE_CFB;
/* PGP uses CFB mode for everything so we change the mode from
the default of CBC to CFB */
krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
( void * ) &mode, CRYPT_CTXINFO_MODE );
/* Generate a salt, derive the key into the context, and insert
it into the action list. Since PGP doesn't perform a key
exchange of a session key, we insert the password-derived
context directly into the main action list */
getNonce( salt, PGP_SALTSIZE );
status = pgpPasswordToKey( createInfo.cryptHandle, value,
valueLength, envelopeInfoPtr->defaultHash,
salt, PGP_ITERATIONS );
if( cryptStatusOK( status ) && \
addAction( &envelopeInfoPtr->actionList, ACTION_CRYPT,
createInfo.cryptHandle ) == NULL )
status = CRYPT_ERROR_MEMORY;
}
else
#endif /* NO_PGP */
{
RESOURCE_DATA msgData;
setResourceData( &msgData, ( void * ) value, valueLength );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_VALUE );
if( cryptStatusOK( status ) )
/* Make sure this key exchange action isn't already present
and insert it into the list */
if( checkAction( envelopeInfoPtr->preActionList,
ACTION_KEYEXCHANGE,
createInfo.cryptHandle ) == ACTION_RESULT_INITED )
status = CRYPT_ERROR_INITED;
else
if( addAction( &envelopeInfoPtr->preActionList,
ACTION_KEYEXCHANGE,
createInfo.cryptHandle ) == NULL )
status = CRYPT_ERROR_MEMORY;
}
if( cryptStatusError( status ) )
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
/* It's a generic "add a context" action, check that everything is valid.
This is necessary because the PGP format doesn't support the full
range of enveloping capabilities */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
{
/* PGP doesn't support both PKC and 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( findAction( envelopeInfoPtr->preActionList,
ACTION_KEYEXCHANGE ) != NULL )
return( CRYPT_ERROR_INITED );
/* PGP handles multiple signers by nesting signed data rather than
attaching multiple signatures, so we can only apply a single
signature per envelope */
if( envInfo == CRYPT_ENVINFO_SIGNATURE && \
envelopeInfoPtr->postActionList != NULL )
return( CRYPT_ERROR_INITED );
/* PGP doesn't allow multiple hash algorithms to be used when signing
data (a follow-on from the way nested sigs are handled) */
if( envInfo == CRYPT_ENVINFO_HASH && \
envelopeInfoPtr->actionList != NULL )
return( CRYPT_ERROR_INITED );
}
switch( envInfo )
{
case CRYPT_ENVINFO_PUBLICKEY:
case CRYPT_ENVINFO_PRIVATEKEY:
actionListHeadPtrPtr = &envelopeInfoPtr->preActionList;
actionType = ACTION_KEYEXCHANGE_PKC;
break;
case CRYPT_ENVINFO_KEY:
if( envelopeInfoPtr->actionList != NULL )
/* We can't add more than one general encryption action */
return( CRYPT_ERROR_INITED );
actionListHeadPtrPtr = &envelopeInfoPtr->actionList;
actionType = ACTION_CRYPT;
break;
case CRYPT_ENVINFO_SESSIONKEY:
/* We can't add more than one session key */
if( envelopeInfoPtr->actionList != NULL )
return( CRYPT_ERROR_INITED );
actionListHeadPtrPtr = &envelopeInfoPtr->actionList;
actionType = ACTION_CRYPT;
/* If there's originator info present, make sure it's consistent
with the new session key */
if( envelopeInfoPtr->iOriginatorChain != CRYPT_ERROR )
{
status = checkFortezzaUsage( cryptHandle, envelopeInfoPtr,
CRYPT_ENVINFO_SESSIONKEY );
if( cryptStatusError( status ) )
return( status );
}
break;
case CRYPT_ENVINFO_HASH:
actionListHeadPtrPtr = &envelopeInfoPtr->actionList;
actionType = ACTION_HASH;
break;
case CRYPT_ENVINFO_SIGNATURE:
actionListHeadPtrPtr = &envelopeInfoPtr->postActionList;
actionType = ACTION_SIGN;
break;
default:
assert( NOTREACHED );
return( CRYPT_ARGERROR_NUM1 );
}
/* Find the insertion point for this action and make sure it isn't
already present. The difference between an inited and present return
code is that an inited response indicates that the user explicitly
added the action and can't add it again while a present response
indicates that the action was added automatically by cryptlib in
response to the user adding some other action and shouldn't be
reported as an error, to the user it doesn't make any difference
whether the same action was added automatically by cryptlib or
explicitly */
actionResult = checkAction( *actionListHeadPtrPtr, actionType, cryptHandle );
if( actionResult == ACTION_RESULT_INITED )
return( CRYPT_ERROR_INITED );
if( actionResult == ACTION_RESULT_PRESENT )
return( CRYPT_OK );
/* Insert the action into the list. If it's a non-PKC context (ie one
whose state can change based on user action), we clone it for our own
use, otherwise we just increment its reference count */
if( actionType == ACTION_HASH || actionType == ACTION_CRYPT )
{
CRYPT_CONTEXT iNewContext;
status = krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_CLONE,
&iNewContext, 0 );
if( cryptStatusError( status ) )
return( status );
cryptHandle = iNewContext;
}
else
status = krnlSendNotifier( cryptHandle, RESOURCE_IMESSAGE_INCREFCOUNT );
actionListPtr = addAction( actionListHeadPtrPtr, actionType, cryptHandle );
if( actionListPtr == NULL )
{
krnlSendNotifier( cryptHandle, RESOURCE_IMESSAGE_DECREFCOUNT );
return( CRYPT_ERROR_MEMORY );
}
if( actionType == ACTION_HASH )
/* Remember that we need to hook the hash action up to a signature
action before we start enveloping data */
actionListPtr->needsController = TRUE;
/* If the newly-inserted action isn't a controlling action, we're done */
if( actionType != ACTION_SIGN )
return( status );
/* If there's no subject hash action available, create one so we can
connect it to the signature action */
if( envelopeInfoPtr->actionList == NULL )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
/* Create a default hash action */
setMessageCreateObjectInfo( &createInfo, envelopeInfoPtr->defaultHash );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
/* Add the hash action to the list */
hashActionPtr = addAction( &envelopeInfoPtr->actionList, ACTION_HASH,
createInfo.cryptHandle );
if( hashActionPtr == NULL )
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( CRYPT_ERROR_MEMORY );
}
/* Remember that the action was added invisibly to the caller so we
don't return an error if they add it as well */
hashActionPtr->addedAutomatically = TRUE;
}
else
/* Find the last hash action which was added */
hashActionPtr = findLastAction( envelopeInfoPtr->actionList,
ACTION_HASH );
/* Connect the signature action to the last hash action which was added
and remember that this action now has a controlling action */
actionListPtr->associatedAction = hashActionPtr;
hashActionPtr->needsController = FALSE;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Envelope Access Routines *
* *
****************************************************************************/
void initResourceHandling( ENVELOPE_INFO *envelopeInfoPtr )
{
/* Set the access method pointers */
envelopeInfoPtr->addInfo = \
( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) ? \
addDeenvelopeInfo : addEnvelopeInfo;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -