📄 certechk.c
字号:
/* If we've reached the end of the list of recognised attributes,
use a non-ID which doesn't match any table entry */
fieldID = CRYPT_UNUSED;
else
/* If we're encoding a subtyped field, the fieldID is the field ID
within the parent field, or the subFieldID */
if( attributeCheckInfo->subtypeParent == attributeListPtr->fieldID )
fieldID = attributeListPtr->subFieldID;
else
/* It's a standard attribute field */
fieldID = attributeListPtr->fieldID;
/* If the field in the attribute list matches the one in the table,
process it and move on to the next one */
if( attributeListPtr != NULL && attributeInfoPtr->fieldID == fieldID )
{
/* If it's a subtyped or CHOICE field, check the components using
their own encoding table */
if( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED || \
attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
{
int status;
/* Switch to the new encoding table and record the fact that
we've done this, and set the new stack top to the level at
which we start encoding the subtype */
if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
{
/* Stack the value start position in the attribute list and
record the fact that we're processing a CHOICE */
stack[ attributeCheckInfo->stackPos ].size = 0;
stack[ attributeCheckInfo->stackPos ].attributeListPtr = attributeListPtr;
stack[ attributeCheckInfo->stackPos++ ].attributeInfoPtr = attributeInfoPtr;
attributeCheckInfo->choiceState = CHOICE_START;
}
attributeCheckInfo->attributeInfoPtr = \
( ATTRIBUTE_INFO * ) attributeInfoPtr->extraData;
attributeCheckInfo->subtypeParent = attributeListPtr->fieldID;
attributeCheckInfo->stackTop = attributeCheckInfo->stackPos;
status = checkAttribute( attributeCheckInfo );
attributeCheckInfo->attributeInfoPtr = attributeInfoPtr;
attributeCheckInfo->subtypeParent = CRYPT_ATTRIBUTE_NONE;
attributeCheckInfo->stackTop = 0;
return( status );
}
/* If there's an extended validation function attached to this field,
call it */
if( attributeInfoPtr->extraData != NULL )
{
VALIDATION_FUNCTION validationFunction = \
( VALIDATION_FUNCTION ) attributeInfoPtr->extraData;
attributeCheckInfo->errorType = validationFunction( attributeListPtr );
if( attributeCheckInfo->errorType != CRYPT_OK )
return( CRYPT_ERROR_INVALID );
}
/* If this is an optional field and the value is the same as the
default value, remember that it doesn't get encoded */
if( ( attributeInfoPtr->flags & FL_DEFAULT ) && \
( attributeInfoPtr->defaultValue == attributeListPtr->value ) )
{
attributeListPtr->flags |= ATTR_FLAG_DEFAULTVALUE;
attributeCheckInfo->attributeListPtr = attributeListPtr->next;
return( CRYPT_OK );
}
/* Remember the encoded size of this field */
attributeListPtr->attributeInfoPtr = attributeInfoPtr;
attributeListPtr->encodedSize = writeAttributeField( NULL, attributeListPtr );
if( attributeCheckInfo->stackPos )
stack[ attributeCheckInfo->stackPos - 1 ].size += attributeListPtr->encodedSize;
/* If this is a CHOICE field, update the choice state */
if( attributeCheckInfo->choiceState != CHOICE_NONE )
{
if( attributeCheckInfo->choiceState == CHOICE_DONE )
{
/* If we've already processed one of the CHOICE options, there
can't be another one present */
attributeCheckInfo->errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
return( CRYPT_ERROR_INVALID );
}
if( attributeCheckInfo->choiceState == CHOICE_START )
/* Remember that we've seen a CHOICE option */
attributeCheckInfo->choiceState = CHOICE_DONE;
}
/* Move on to the next attribute field */
attributeCheckInfo->attributeListPtr = attributeListPtr->next;
return( CRYPT_OK );
}
/* If it's an attributeTypeAndValue sequence, check whether it contains
the field we want */
if( attributeInfoPtr->flags & FL_IDENTIFIER )
{
BOOLEAN endOfAttributeField = FALSE;
if( !checkComponentPresent( fieldID, &attributeInfoPtr ) )
{
/* Since we've jumped over several items we may be pointing at an
end-of-sequence flag for which no sequence start was stacked,
so we skip the stack update step */
attributeCheckInfo->attributeInfoPtr = attributeInfoPtr;
return( OK_SPECIAL );
}
/* Stack the position of the sequence start and the following OID */
stack[ attributeCheckInfo->stackPos ].size = 0;
stack[ attributeCheckInfo->stackPos ].attributeListPtr = attributeListPtr;
stack[ attributeCheckInfo->stackPos++ ].attributeInfoPtr = attributeInfoPtr++;
stack[ attributeCheckInfo->stackPos ].size = 0;
stack[ attributeCheckInfo->stackPos ].attributeListPtr = attributeListPtr;
stack[ attributeCheckInfo->stackPos++ ].attributeInfoPtr = attributeInfoPtr;
/* If the OID entry is marked as the end-of-sequence, there are no
parameters attached so we move on to the next entry */
if( attributeInfoPtr->flags & FL_SEQEND_MASK )
endOfAttributeField = TRUE;
/* Sometimes the OID is followed by a fixed-value blob field which
constitutes parameters for the OID, if this is present we stack it
as well */
if( attributeInfoPtr[ 1 ].flags & FL_NONENCODING )
{
attributeInfoPtr++;
stack[ attributeCheckInfo->stackPos ].size = 0;
stack[ attributeCheckInfo->stackPos ].attributeListPtr = attributeListPtr;
stack[ attributeCheckInfo->stackPos++ ].attributeInfoPtr = attributeInfoPtr;
/* 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 */
attributeCheckInfo->attributeListPtr = attributeListPtr->next;
return( CRYPT_OK );
}
/* If it's a sequence/set or a non-encoding value then it's a nop 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 */
stack[ attributeCheckInfo->stackPos ].size = 0;
stack[ attributeCheckInfo->stackPos ].attributeListPtr = attributeListPtr;
stack[ attributeCheckInfo->stackPos++ ].attributeInfoPtr = attributeInfoPtr;
return( CRYPT_OK );
}
/* 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 */
static int checkAttribute( ATTRIBUTE_CHECK_INFO *attributeCheckInfo )
{
BOOLEAN attributeContinues;
assert( isWritePtr( attributeCheckInfo, ATTRIBUTE_CHECK_INFO ) );
/* Step through the attribute comparing the fields which are present in
the attribute list with the fields which should be present according
to the table, and set encoding sync points as required */
do
{
int status;
/* 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 */
updateStackedInfo( attributeCheckInfo->stack,
&attributeCheckInfo->stackPos,
decodeNestingLevel( attributeCheckInfo->attributeInfoPtr->flags ),
TRUE );
}
/* If it's another instance of the same item, don't move on to the
next table entry */
if( attributeCheckInfo->attributeListPtr != NULL && \
attributeCheckInfo->attributeListPtr->next != NULL && \
( attributeCheckInfo->attributeListPtr->fieldID == \
attributeCheckInfo->attributeListPtr->next->fieldID ) && \
( attributeCheckInfo->attributeListPtr->subFieldID == \
attributeCheckInfo->attributeListPtr->next->subFieldID ) )
{
/* Currently we don't allow the creation of multivalued
instances of fields, although we can read certs which contain
them */
assert( NOTREACHED );
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 );
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 */
updateStackedInfo( attributeCheckInfo->stack, &attributeCheckInfo->stackPos,
attributeCheckInfo->stackPos - attributeCheckInfo->stackTop,
FALSE );
return( CRYPT_OK );
}
/* Check the entire list of attributes */
int checkAttributes( const ATTRIBUTE_TYPE attributeType,
const ATTRIBUTE_LIST *listHeadPtr,
CRYPT_ATTRIBUTE_TYPE *errorLocus,
CRYPT_ERRTYPE_TYPE *errorType )
{
ATTRIBUTE_CHECK_INFO attributeCheckInfo;
const ATTRIBUTE_INFO *attributeInfoStartPtr = \
selectAttributeInfo( attributeType );
ATTRIBUTE_LIST *attributeListPtr;
/* If we've already done a validation pass, some of the fields will
contain values which were previously set, so before we begin we walk
down the list resetting the fields which are updated by this
function */
for( attributeListPtr = ( ATTRIBUTE_LIST * ) listHeadPtr;
attributeListPtr != NULL && attributeListPtr->fieldID != CRYPT_ATTRIBUTE_NONE;
attributeListPtr = attributeListPtr->next )
{
attributeListPtr->attributeInfoPtr = NULL;
attributeListPtr->encodedSize = attributeListPtr->fifoPos = \
attributeListPtr->fifoEnd = 0;
attributeListPtr->flags &= ~ATTR_FLAG_DEFAULTVALUE;
}
/* 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 */
while( attributeCheckInfo.attributeListPtr != NULL && \
attributeCheckInfo.attributeListPtr->fieldID != CRYPT_ATTRIBUTE_NONE )
{
int status;
/* Find the start of this attribute in the attribute info table and
remember it as an encoding sync 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 */
while( attributeCheckInfo.attributeInfoPtr->fieldID != \
attributeCheckInfo.attributeListPtr->attributeID )
attributeCheckInfo.attributeInfoPtr++;
while( attributeCheckInfo.attributeInfoPtr != attributeInfoStartPtr && \
attributeCheckInfo.attributeInfoPtr[ -1 ].fieldID == FIELDID_FOLLOWS )
attributeCheckInfo.attributeInfoPtr--;
/* Check this attribute */
status = checkAttribute( &attributeCheckInfo );
if( cryptStatusError( status ) )
{
*errorLocus = attributeCheckInfo.errorLocus;
*errorType = attributeCheckInfo.errorType;
return( status );
}
}
return( CRYPT_OK );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -