📄 ext_chk.c
字号:
return( status );
/* If the fields are fixed-value we always move on to the next
entry since there are no user-supplied parameters present */
endOfAttributeField = TRUE;
}
attributeCheckInfo->attributeInfoPtr = attributeInfoPtr;
if( endOfAttributeField )
{
/* If this is all that needs to be encoded move on to the next
attribute field */
if( attributeListPtr == NULL )
attributeCheckInfo->attributeListPtr = NULL;
else
attributeCheckInfo->attributeListPtr = attributeListPtr->next;
}
return( CRYPT_OK );
}
/* If it's a SEQUENCE/SET or a non-encoding value then it's a no-op entry
used only for encoding purposes and can be skipped, however we need to
remember it for later encoding */
if( attributeInfoPtr->fieldType == BER_SEQUENCE || \
attributeInfoPtr->fieldType == BER_SET || \
attributeInfoPtr->flags & FL_NONENCODING )
{
/* Stack the sequence or value start position in the attribute list */
return( stackInfo( attributeCheckInfo, attributeListPtr,
attributeInfoPtr ) );
}
/* If it's a non-optional field and the attribute field doesn't match,
it's an error - attribute attributeID is missing field
attributeInfoPtr->fieldID (optional subfield
attributeInfoPtr->subFieldID) (set by the error handler in the calling
code) */
if( !( attributeInfoPtr->flags & FL_OPTIONAL ) )
{
attributeCheckInfo->errorType = CRYPT_ERRTYPE_ATTR_ABSENT;
return( CRYPT_ERROR_NOTINITED );
}
return( CRYPT_OK );
}
/* Check an individual attribute */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int checkAttribute( INOUT_ARRAY( ATTRIBUTE_CHECK_INFO ) \
ATTRIBUTE_CHECK_INFO *attributeCheckInfo )
{
ATTRIBUTE_LIST *restartEntry = NULL;
ATTRIBUTE_INFO *restartPoint = NULL;
int restartStackPos = 0, iterationCount = 0;
BOOLEAN attributeContinues;
assert( isWritePtr( attributeCheckInfo, \
sizeof( ATTRIBUTE_CHECK_INFO ) ) );
/* Step through the attribute comparing the fields that are present in
the attribute list with the fields that should be present according
to the table and set encoding synchronisation points as required */
do
{
int status;
/* Sanity check to make sure that we don't fall off the end of the
encoding table */
ENSURES( attributeCheckInfo->attributeInfoPtr->fieldID != CRYPT_ERROR );
/* Check whether this is a repeated instance of the same attribute
and if it is remember the encoding restart point. We have to do
this before we check the attribute info because it usually
updates the info after the check */
if( restartEntry == NULL && \
attributeCheckInfo->attributeListPtr != NULL && \
attributeCheckInfo->attributeListPtr->next != NULL && \
( attributeCheckInfo->attributeListPtr->fieldID == \
attributeCheckInfo->attributeListPtr->next->fieldID ) && \
( attributeCheckInfo->attributeListPtr->subFieldID == \
attributeCheckInfo->attributeListPtr->next->subFieldID ) )
{
restartEntry = attributeCheckInfo->attributeListPtr;
restartPoint = attributeCheckInfo->attributeInfoPtr + 1;
restartStackPos = attributeCheckInfo->stackPos + 1;
}
/* Check the current encoding table entry */
status = checkAttributeEntry( attributeCheckInfo );
if( status != OK_SPECIAL )
{
if( cryptStatusError( status ) )
{
attributeCheckInfo->errorLocus = \
attributeCheckInfo->attributeInfoPtr->fieldID;
return( status );
}
/* If this is the end of a constructed item unstack it and
update the attribute list entry with the length information.
If it's a sequence with all fields optional (so that nothing
gets encoded) we don't do anything */
status = updateStackedInfo( attributeCheckInfo->stack,
attributeCheckInfo->stackPos,
&attributeCheckInfo->stackPos,
decodeNestingLevel( attributeCheckInfo->attributeInfoPtr->flags ),
TRUE );
if( cryptStatusError( status ) )
return( status );
}
/* If there's another instance of the same item, don't move on to
the next table entry */
if( restartEntry != NULL && \
restartEntry != attributeCheckInfo->attributeListPtr )
{
#if 0
/* Currently we don't allow the creation of multivalued
instances of fields although we can read certificates that
contain them */
retIntError();
#endif /* 0 */
/* Restart at the table entry for the previous instance of the
item and adjust the stack to match */
attributeCheckInfo->attributeInfoPtr = restartPoint;
attributeContinues = TRUE;
if( attributeCheckInfo->stackPos > restartStackPos )
{
status = updateStackedInfo( attributeCheckInfo->stack,
attributeCheckInfo->stackPos,
&attributeCheckInfo->stackPos,
attributeCheckInfo->stackPos - \
restartStackPos, TRUE );
if( cryptStatusError( status ) )
return( status );
}
restartEntry = NULL;
restartPoint = NULL;
restartStackPos = 0;
continue;
}
/* Move on to the next table entry. We have to check the
continuation flag before we move to the next table entry in order
to include processing of the last field in an attribute */
attributeContinues = \
( attributeCheckInfo->attributeInfoPtr->flags & FL_MORE ) ? \
TRUE : FALSE;
attributeCheckInfo->attributeInfoPtr++;
}
while( attributeContinues && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
attributeCheckInfo->choiceState = CHOICE_NONE;
/* We've reached the end of the attribute, if there are still constructed
objects stacked, unstack them and update their length information. If
it's a sequence with all fields optional (so that nothing gets
encoded) we don't do anything */
return( updateStackedInfo( attributeCheckInfo->stack,
attributeCheckInfo->stackPos,
&attributeCheckInfo->stackPos,
attributeCheckInfo->stackPos - \
attributeCheckInfo->stackTop, FALSE ) );
}
/* Check the entire list of attributes */
CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) \
int checkAttributes( IN_ENUM( ATTRIBUTE ) const ATTRIBUTE_TYPE attributeType,
const ATTRIBUTE_LIST *listHeadPtr,
OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
CRYPT_ATTRIBUTE_TYPE *errorLocus,
OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
CRYPT_ERRTYPE_TYPE *errorType )
{
ATTRIBUTE_CHECK_INFO attributeCheckInfo;
const ATTRIBUTE_INFO *attributeInfoStartPtr = \
selectAttributeInfo( attributeType );
ATTRIBUTE_LIST *attributeListPtr;
int iterationCount;
assert( isReadPtr( listHeadPtr, sizeof( ATTRIBUTE_LIST ) ) );
assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
REQUIRES( attributeType == ATTRIBUTE_CERTIFICATE || \
attributeType == ATTRIBUTE_CMS );
REQUIRES( attributeInfoStartPtr != NULL );
/* If we've already done a validation pass some of the fields will
contain values that were previously set so before we begin we walk
down the list resetting the fields that are updated by this
function */
for( attributeListPtr = ( ATTRIBUTE_LIST * ) listHeadPtr, \
iterationCount = 0;
attributeListPtr != NULL && \
isValidAttributeField( attributeListPtr ) && \
iterationCount < FAILSAFE_ITERATIONS_MAX;
attributeListPtr = attributeListPtr->next, iterationCount++ )
{
if( attributeListPtr->next != NULL && \
isValidAttributeField( attributeListPtr->next ) && \
attributeListPtr->attributeID > \
attributeListPtr->next->attributeID )
{
/* Safety check in case of an invalid attribute list */
retIntError();
}
attributeListPtr->attributeInfoPtr = NULL;
attributeListPtr->encodedSize = attributeListPtr->fifoPos = \
attributeListPtr->fifoEnd = 0;
attributeListPtr->flags &= ~ATTR_FLAG_DEFAULTVALUE;
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );
/* Set up the attribute-checking state information */
memset( &attributeCheckInfo, 0, sizeof( ATTRIBUTE_CHECK_INFO ) );
attributeCheckInfo.attributeListPtr = ( ATTRIBUTE_LIST * ) listHeadPtr;
attributeCheckInfo.attributeInfoPtr = ( ATTRIBUTE_INFO * ) attributeInfoStartPtr;
/* Walk down the list of known attributes checking each one for
consistency */
for( iterationCount = 0;
attributeCheckInfo.attributeListPtr != NULL && \
attributeCheckInfo.attributeListPtr->fieldID != CRYPT_ATTRIBUTE_NONE && \
iterationCount < FAILSAFE_ITERATIONS_MAX;
iterationCount++ )
{
int innerIterationCount, status;
/* Find the start of this attribute in the attribute info table and
remember it as an encoding synchronisation point. Comparing the
field ID with the attribute ID is usually valid because the
attribute info table always begins the series of entries for an
attribute with the attribute ID. The one exception is where the
attribute ID is the same as the field ID but they're separate
entries in the table, in which case the first entries will
contain a FIELDID_FOLLOWS code to indicate that a following field
contains the attribute/fieldID */
for( innerIterationCount = 0;
( attributeCheckInfo.attributeInfoPtr->fieldID != \
attributeCheckInfo.attributeListPtr->attributeID ) && \
attributeCheckInfo.attributeInfoPtr->fieldID != CRYPT_ERROR && \
innerIterationCount < FAILSAFE_ITERATIONS_LARGE;
attributeCheckInfo.attributeInfoPtr++, innerIterationCount++ );
ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_LARGE );
ENSURES( attributeCheckInfo.attributeInfoPtr->fieldID != CRYPT_ERROR );
for( innerIterationCount = 0;
attributeCheckInfo.attributeInfoPtr != attributeInfoStartPtr && \
attributeCheckInfo.attributeInfoPtr[ -1 ].fieldID == FIELDID_FOLLOWS && \
innerIterationCount < FAILSAFE_ITERATIONS_LARGE;
attributeCheckInfo.attributeInfoPtr--, innerIterationCount++ );
ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_LARGE );
/* Check this attribute */
status = checkAttribute( &attributeCheckInfo );
if( cryptStatusError( status ) )
{
*errorLocus = attributeCheckInfo.errorLocus;
*errorType = attributeCheckInfo.errorType;
return( status );
}
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );
return( CRYPT_OK );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -