📄 res_actn.c
字号:
case ACTION_KEYEXCHANGE_PKC:
case ACTION_SIGN:
/* It's a PKC object, get the key ID */
setMessageData( &msgData, keyID, KEYID_SIZE );
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID );
break;
case ACTION_HASH:
case ACTION_MAC:
case ACTION_CRYPT:
/* It's a raw action object, get the algorithm */
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
break;
default:
retIntError_Ext( ACTION_RESULT_ERROR );
}
if( cryptStatusError( status ) )
return( ACTION_RESULT_ERROR );
/* Walk down the list from the first to the last action in the action
group checking each one in turn */
for( actionListPtr = findAction( actionListPtr, actionType ), \
iterationCount = 0;
actionListPtr != NULL && actionListPtr->action == actionType && \
iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ )
{
BOOLEAN isDuplicate = FALSE;
int actionAlgo;
/* Make sure that we haven't added this action already. This can
get a bit tricky both because detecting some types of duplicates
is rather hard and because the definition of what's an invalid
duplicate varies somewhat. For a hash, MAC, and encryption
action we only allow one action of a given algorithm type to
be added. For a PKC key exchange or signature action we only
allow one action for a given key to be added. For a conventional
key exchange action we should in theory check for duplicates in
some form but it's not certain what constitutes a duplicate (for
example are two otherwise identical actions with a different
number of key setup iterations considered duplicates or not?) so
for now we assume that the user won't do anything silly (in any
case for any key exchange action the only thing that a duplicate
will do is result in unnecessary bloating of the envelope
header).
In addition to the more sophisticated checks we also perform a
few more basic ones for the same object being added twice, which
doesn't catch e.g. inadvertent use of the same keying material
but does catch simple programming errors */
if( actionListPtr->iCryptHandle == cryptHandle )
return( ACTION_RESULT_INITED );
switch( actionType )
{
case ACTION_KEYEXCHANGE:
/* It's a conventional key exchange, there's not much that
we can check */
break;
case ACTION_KEYEXCHANGE_PKC:
case ACTION_SIGN:
/* It's a PKC key exchange or signature action, compare the
two objects by comparing their keys */
setMessageData( &msgData, keyID, KEYID_SIZE );
if( cryptStatusOK( \
krnlSendMessage( actionListPtr->iCryptHandle,
IMESSAGE_COMPARE, &msgData,
MESSAGE_COMPARE_KEYID ) ) )
isDuplicate = TRUE;
break;
case ACTION_HASH:
case ACTION_MAC:
case ACTION_CRYPT:
/* It's a hash/MAC or session key object, compare the two
objects by comparing their algorithms */
if( cryptStatusOK( \
krnlSendMessage( actionListPtr->iCryptHandle,
IMESSAGE_GETATTRIBUTE, &actionAlgo,
CRYPT_CTXINFO_ALGO ) ) && \
actionAlgo == cryptAlgo )
isDuplicate = TRUE;
break;
}
if( isDuplicate )
{
/* If the action was added automatically/implicitly as the
result of adding another action then the first attempt to add
it explicitly by the caller isn't an error. The caller will
treat the ACTION_RESULT_PRESENT code as CRYPT_OK */
if( actionListPtr->flags & ACTION_ADDEDAUTOMATICALLY )
{
actionListPtr->flags &= ~ACTION_ADDEDAUTOMATICALLY;
return( ACTION_RESULT_PRESENT );
}
return( ACTION_RESULT_INITED );
}
}
ENSURES_EXT( ( iterationCount < FAILSAFE_ITERATIONS_MED ), \
ACTION_RESULT_ERROR );
return( ACTION_RESULT_OK );
}
/* An indirect action-check function that uses a caller-supplied callback to
verify each action */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int checkActionIndirect( const ACTION_LIST *actionListStart,
IN CHECKACTIONFUNCTION checkActionFunction,
IN_INT_Z const int intParam )
{
const ACTION_LIST *actionListPtr;
int iterationCount;
assert( isReadPtr( actionListStart, sizeof( ACTION_LIST ) ) );
REQUIRES( checkActionFunction != NULL );
for( actionListPtr = actionListStart, iterationCount = 0;
actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ )
{
const int status = checkActionFunction( actionListPtr, intParam );
if( cryptStatusError( status ) )
return( status );
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
return( CRYPT_OK );
}
/* Perform a sanity-check to ensure that the actions in an envelope are
consistent. There are two approaches to this, take the envelope usage
and check that everything is consistent with it, or take the actions
and make sure that they're consistent with the usage (and each other).
We perform the latter type of check, which is somewhat simpler. The
requirements that we enforce are:
| Pre | In | Post |
--------+-----------+-----------+-----------+-----
SIG | - | Hash | Sig | CMS
| - | 1x Hash | 1x Sig | PGP
--------+-----------+-----------+-----------+-----
MAC | Keyex,PKC | 1x MAC | - | CMS
| - | - | - | PGP
--------+-----------+-----------+-----------+-----
COPR | - | - | - | CMS
| - | - | - | PGP
--------+-----------+-----------+-----------+-----
ENCR | Keyex,PKC | Crypt | - | CMS
| PKC | 1x Crypt | - | PGP
In the case of ENCR the pre-actions can be absent if we're using raw
session-key encryption */
CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
BOOLEAN checkActions( INOUT ENVELOPE_INFO *envelopeInfoPtr )
{
ACTION_LIST *actionListPtr;
int iterationCount;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
/* If there are no pre-, post-, or main actions (i.e. it's a compressed
or data-only envelope), we're done */
if( envelopeInfoPtr->actionList == NULL )
{
/* Make sure that the envelope has the appropriate usage for these
actions */
if( envelopeInfoPtr->usage != ACTION_COMPRESS && \
envelopeInfoPtr->usage != ACTION_NONE )
return( FALSE );
/* There can be no pre- or post-actions present for this usage */
if( envelopeInfoPtr->preActionList != NULL || \
envelopeInfoPtr->postActionList != NULL )
return( FALSE );
return( TRUE );
}
/* If there are pre-actions it has to be a key exchange followed by
encryption or MAC actions */
if( envelopeInfoPtr->preActionList != NULL )
{
int actionCount = 0;
/* Make sure that the envelope has the appropriate usage for these
actions */
if( envelopeInfoPtr->usage != ACTION_CRYPT && \
envelopeInfoPtr->usage != ACTION_MAC )
return( FALSE );
/* Pre-actions can only be key exchange actions and have to be sorted
by action group */
for( actionListPtr = envelopeInfoPtr->preActionList, \
iterationCount = 0;
actionListPtr != NULL && \
actionListPtr->action == ACTION_KEYEXCHANGE_PKC && \
iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ );
ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MED );
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
actionListPtr != NULL )
{
/* PGP can't have any conventional keyex actions since the
password is used to directly derive the session key */
return( FALSE );
}
for( iterationCount = 0;
actionListPtr != NULL && \
actionListPtr->action == ACTION_KEYEXCHANGE && \
iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ );
ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MED );
if( actionListPtr != NULL )
return( FALSE );
ENSURES_B( envelopeInfoPtr->actionList != NULL );
/* Key exchange must be followed by a single crypt or one or more
MAC actions */
for( actionListPtr = envelopeInfoPtr->actionList, iterationCount = 0;
actionListPtr != NULL && \
iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ )
{
if( actionListPtr->action == ACTION_CRYPT )
actionCount++;
else
{
if( actionListPtr->action != ACTION_MAC )
return( FALSE );
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
{
/* PGP doesn't support MAC'd envelopes */
return( FALSE );
}
}
}
ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MED );
if( actionCount > 1 )
return( FALSE );
/* There can't be any post-actions */
if( envelopeInfoPtr->postActionList != NULL )
return( FALSE );
return( TRUE );
}
/* If there are post-actions it has to be a hash follwed by signature
actions */
if( envelopeInfoPtr->postActionList != NULL )
{
int hashActionCount = 0, sigActionCount = 0;
/* Make sure that the envelope has the appropriate usage for these
actions */
if( envelopeInfoPtr->usage != ACTION_SIGN )
return( FALSE );
/* There can't be any pre-actions */
if( envelopeInfoPtr->preActionList != NULL )
return( FALSE );
/* The signature must be preceded by one or more hash actions */
if( envelopeInfoPtr->actionList == NULL )
return( FALSE );
for( actionListPtr = envelopeInfoPtr->actionList, iterationCount = 0;
actionListPtr != NULL && \
iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ )
{
if( actionListPtr->action != ACTION_HASH )
return( FALSE );
hashActionCount++;
}
ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MED );
/* PGP can only have a single hash per signed envelope */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && hashActionCount > 1 )
return( FALSE );
/* Hash actions must be followed by one or more signature actions */
for( actionListPtr = envelopeInfoPtr->postActionList, \
iterationCount = 0;
actionListPtr != NULL && \
iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ )
{
if( actionListPtr->action != ACTION_SIGN )
return( FALSE );
sigActionCount++;
}
ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MED );
/* PGP can only have a single signature, multiple signatures are
handled by nesting envelopes */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && sigActionCount > 1 )
return( FALSE );
return( TRUE );
}
/* If there's a standalone session-key encryption action, it has to be
the only action present */
actionListPtr = envelopeInfoPtr->actionList;
ENSURES_B( actionListPtr != NULL );
if( actionListPtr->action == ACTION_CRYPT )
{
/* Make sure that the envelope has the appropriate usage for these
actions */
if( envelopeInfoPtr->usage != ACTION_CRYPT )
return( FALSE );
/* There can only be one encryption action present */
if( actionListPtr->next != NULL )
return( FALSE );
return( TRUE );
}
/* If we're processing PGP-encrypted data with an MDC at the end of the
encrypted data then it's possible to have an encryption envelope with
a hash action (which must be followed by an encryption action) */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
actionListPtr->action == ACTION_HASH && \
actionListPtr->next != NULL && \
actionListPtr->next->action == ACTION_CRYPT )
{
ACTION_LIST *nextActionPtr = actionListPtr->next;
/* Make sure that the envelope has the appropriate usage for these
actions */
if( envelopeInfoPtr->usage != ACTION_CRYPT )
return( FALSE );
/* Make sure that the encryption action is the only other action */
if( nextActionPtr->action != ACTION_CRYPT || \
nextActionPtr->next != NULL )
return( FALSE );
return( TRUE );
}
/* If it's a MACd envelope there can only be a single MAC action
present */
if( envelopeInfoPtr->usage == ACTION_MAC )
{
/* Make sure that there's only a single MAC action present */
if( actionListPtr->action != ACTION_MAC || \
actionListPtr->next != NULL )
return( FALSE );
return( TRUE );
}
/* Anything else has to be a signing envelope */
if( envelopeInfoPtr->usage != ACTION_SIGN )
return( FALSE );
/* When we're de-enveloping a signed envelope we can have standalone
hash actions before we get to the signature data and add post-
actions */
if( ( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
actionListPtr->action == ACTION_HASH )
{
for( iterationCount = 0; \
actionListPtr != NULL && \
iterationCount < FAILSAFE_ITERATIONS_MED;
actionListPtr = actionListPtr->next, iterationCount++ )
{
if( actionListPtr->action != ACTION_HASH )
return( FALSE );
}
ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MED );
return( TRUE );
}
/* Everything else is an error */
return( FALSE );
}
#endif /* USE_ENVELOPES */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -