📄 resource.c
字号:
envelopeInfoPtr->actionList != NULL ) )
return( CRYPT_ERROR_INITED );
/* Create the appropriate encryption context. We have to be careful
to ensure that 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 that 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_TYPE ) CRYPT_MODE_CBC, 0 ) ) ) )
cryptAlgo = CRYPT_ALGO_3DES;
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
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 */
#ifdef USE_PGP
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
{
RESOURCE_DATA msgData;
BYTE salt[ PGP_SALTSIZE ];
static const CRYPT_MODE_TYPE 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, 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 */
setMessageData( &msgData, salt, PGP_SALTSIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( cryptStatusOK( status ) )
status = pgpPasswordToKey( createInfo.cryptHandle,
value, valueLength,
envelopeInfoPtr->defaultHash,
salt, PGP_ITERATIONS );
if( cryptStatusOK( status ) && \
addAction( &envelopeInfoPtr->actionList,
envelopeInfoPtr->memPoolState, ACTION_CRYPT,
createInfo.cryptHandle ) == NULL )
status = CRYPT_ERROR_MEMORY;
}
else
#endif /* USE_PGP */
{
RESOURCE_DATA msgData;
setMessageData( &msgData, ( void * ) value, valueLength );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_VALUE );
if( cryptStatusOK( status ) )
{
/* Make sure that 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,
envelopeInfoPtr->memPoolState,
ACTION_KEYEXCHANGE,
createInfo.cryptHandle ) == NULL )
status = CRYPT_ERROR_MEMORY;
}
}
if( cryptStatusError( status ) )
krnlSendNotifier( createInfo.cryptHandle, 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:
/* PGP doesn't allow KEK-based encryption, so if it's a PGP
envelope we drop through and treat it as a session key */
if( envelopeInfoPtr->type != CRYPT_FORMAT_PGP )
{
actionListHeadPtrPtr = &envelopeInfoPtr->preActionList;
actionType = ACTION_KEYEXCHANGE;
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;
#ifdef USE_FORTEZZA
/* If there's originator info present, make sure that it's
consistent with the new session key */
if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
{
status = checkFortezzaUsage( cryptHandle, envelopeInfoPtr,
CRYPT_ENVINFO_SESSIONKEY );
if( cryptStatusError( status ) )
return( status );
}
#endif /* USE_FORTEZZA */
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 that 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-idempotent context
(i.e. one whose state can change based on user actions), we clone it
for our own use, otherwise we just increment its reference count */
if( actionType == ACTION_HASH || actionType == ACTION_CRYPT )
{
CRYPT_ALGO_TYPE cryptAlgo;
MESSAGE_CREATEOBJECT_INFO createInfo;
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
{
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
}
if( cryptStatusError( status ) )
return( status );
status = krnlSendMessage( cryptHandle, IMESSAGE_CLONE, NULL,
createInfo.cryptHandle );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
cryptHandle = createInfo.cryptHandle;
}
else
status = krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT );
actionListPtr = addAction( actionListHeadPtrPtr,
envelopeInfoPtr->memPoolState, actionType,
cryptHandle );
if( actionListPtr == NULL )
{
krnlSendNotifier( cryptHandle, 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->flags |= ACTION_NEEDSCONTROLLER;
/* 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,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
/* Add the hash action to the list */
hashActionPtr = addAction( &envelopeInfoPtr->actionList,
envelopeInfoPtr->memPoolState, ACTION_HASH,
createInfo.cryptHandle );
if( hashActionPtr == NULL )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( CRYPT_ERROR_MEMORY );
}
/* Remember that the action was added invisibly to the caller so that
we don't return an error if they add it as well */
hashActionPtr->flags |= ACTION_ADDEDAUTOMATICALLY;
}
else
/* Find the last hash action that was added */
hashActionPtr = findLastAction( envelopeInfoPtr->actionList,
ACTION_HASH );
/* Connect the signature action to the last hash action that was added
and remember that this action now has a controlling action */
actionListPtr->associatedAction = hashActionPtr;
hashActionPtr->flags &= ~ACTION_NEEDSCONTROLLER;
return( CRYPT_OK );
}
/* Check the consistency of envelope resources */
static CRYPT_ATTRIBUTE_TYPE checkMissingInfo( ENVELOPE_INFO *envelopeInfoPtr )
{
ACTION_LIST *actionListPtr;
BOOLEAN needsSigAction = FALSE;
/* If there are signature-related options present (signature envelope,
detached-sig flag set, hash context present, or CMS attributes or a
TSA session present), there must be a signing key also present */
for( actionListPtr = envelopeInfoPtr->postActionList;
actionListPtr != NULL; actionListPtr = actionListPtr->next )
if( actionListPtr->iExtraData != CRYPT_ERROR || \
actionListPtr->iTspSession != CRYPT_ERROR )
{
needsSigAction = TRUE;
break;
}
if( ( envelopeInfoPtr->usage == ACTION_SIGN || \
envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG || \
findAction( envelopeInfoPtr->actionList, ACTION_HASH ) != NULL || \
needsSigAction ) && \
findAction( envelopeInfoPtr->postActionList, ACTION_SIGN ) == NULL )
return( CRYPT_ENVINFO_SIGNATURE );
/* If it's a MAC envelope, there must be at least one key exchange action
present. A few obscure operations may set the usage without setting a
key exchange action, for example making the envelope a MAC envelope
simply indicates that any future key exchange actions should be used
for MAC'ing rather than encryption */
if( envelopeInfoPtr->usage == ACTION_MAC && \
findAction( envelopeInfoPtr->preActionList, \
ACTION_KEYEXCHANGE_PKC ) == NULL && \
findAction( envelopeInfoPtr->preActionList, \
ACTION_KEYEXCHANGE ) == NULL )
/* We return the most generic CRYPT_ENVINFO_KEY error code, since
there are several possible missing attribute types that could
be required */
return( CRYPT_ENVINFO_KEY );
/* If it's an encryption envelope, there must be a key present at some
level. This situation doesn't normally occur since the higher-level
code will only set the usage to encryption once a key exchange action
has been added, but we check anyway just to be safe */
if( envelopeInfoPtr->usage == ACTION_CRYPT && \
findAction( envelopeInfoPtr->preActionList, \
ACTION_KEYEXCHANGE_PKC ) == NULL && \
findAction( envelopeInfoPtr->preActionList, \
ACTION_KEYEXCHANGE ) == NULL && \
findAction( envelopeInfoPtr->actionList, ACTION_CRYPT ) == NULL )
return( CRYPT_ENVINFO_KEY );
/* If there's an originator present, there must be a matching public-key
action present */
if( envelopeInfoPtr->usage == ACTION_CRYPT && \
envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR && \
findAction( envelopeInfoPtr->preActionList,
ACTION_KEYEXCHANGE_PKC ) == NULL )
return( CRYPT_ENVINFO_PUBLICKEY );
return( CRYPT_ATTRIBUTE_NONE );
}
/****************************************************************************
* *
* Envelope Access Routines *
* *
****************************************************************************/
void initResourceHandling( ENVELOPE_INFO *envelopeInfoPtr )
{
/* Set the access method pointers */
if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
envelopeInfoPtr->addInfo = addDeenvelopeInfo;
else
{
envelopeInfoPtr->addInfo = addEnvelopeInfo;
envelopeInfoPtr->checkMissingInfo = checkMissingInfo;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -