⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ext_chk.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:

		/* If the field is present in this attributeTypeAndValue, return */
		if( attributeInfoPtr->fieldID == fieldID )
			return( CRYPT_OK );

		/* If we're at the end of the attribute or the attributeTypeAndValue,
		   exit the loop before adjusting the attributeInfoPtr so that we're
		   still pointing at the end-of-attribute field */
		if( nestLevel <= 0 || !( attributeInfoPtr->flags & FL_MORE ) )
			break;

		attributeInfoPtr++;
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );

	/* The field isn't present, update the pointer to the next
	   attributeTypeAndValue or the end of the attribute */
	*attributeInfoPtrPtr = ( ATTRIBUTE_INFO * ) attributeInfoPtr;
	return( CRYPT_ERROR_NOTFOUND );
	}

/* State machine for checking a CHOICE.  When we get to the start of a
   CHOICE we move from CHOICE_NONE to CHOICE_START.  Once we've checked one
   of the CHOICE options we move to CHOICE_DONE.  If a further option is
   found in the CHOICE_DONE state we record an error.  This is a somewhat
   crude mechanism that works because the only CHOICE fields that can't be
   handled by rewriting them as alternative representations are complete
   attributes so that the CHOICE applies over the entire attribute.  If a
   CHOICE is ever present as an attribute subfield then the checking would 
   be handled by recursively checking it as a subtyped field */

typedef enum { CHOICE_NONE, CHOICE_START, CHOICE_DONE } CHOICE_STATE;

/* Check an entry in the attribute table.  While we're performing the check
   we need to pass a lot of state information around, this is contained in
   the following structure */

typedef struct {
	/* State information.  When we're encoding a subtyped field (using an
	   alternative encoding table) we need to remember the field ID of the
	   parent to both tell the encoding routines that we're using an
	   alternative encoding table and to remember the overall field ID so we
	   don't treat two adjacent field subfields as though they were part of
	   the same parent field.  If we're not currently encoding a subtyped
	   field, this field is set to CRYPT_ATTRIBUTE_NONE */
	ATTRIBUTE_LIST *attributeListPtr;	/* Position in attribute list */
	ATTRIBUTE_INFO *attributeInfoPtr;	/* Position in attribute table */
	CRYPT_ATTRIBUTE_TYPE subtypeParent;	/* Parent of subtype being processed */
	CHOICE_STATE choiceState;			/* State of CHOICE processing */

	/* Encoding stack.  When we're encoding subfields the stack contains 
	   items from both the subfield and the encapsulating field so we also
	   record the current stack top to make sure that we don't go past this 
	   level when popping items after we've finished encoding a subfield */
	ATTRIBUTE_STACK stack[ ATTRIBUTE_STACKSIZE + 8 ];
	int stackPos;					/* Encoding stack position */
	int stackTop;

	/* Error information */
	CRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */
	int errorType;					/* Error type */
	} ATTRIBUTE_CHECK_INFO;

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int stackInfo( INOUT_ARRAY( ATTRIBUTE_CHECK_INFO ) \
						ATTRIBUTE_CHECK_INFO *attributeCheckInfo,
					  IN_OPT ATTRIBUTE_LIST *attributeListPtr,
					  IN ATTRIBUTE_INFO *attributeInfoPtr )
	{
	ATTRIBUTE_STACK *stack = attributeCheckInfo->stack;

	assert( isWritePtr( attributeCheckInfo, \
						sizeof( ATTRIBUTE_CHECK_INFO ) ) );
	assert( attributeListPtr == NULL || \
			isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );
	assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );

	REQUIRES( attributeCheckInfo->stackPos >= 0 && \
			  attributeCheckInfo->stackPos < ATTRIBUTE_STACKSIZE - 1 );

	stack[ attributeCheckInfo->stackPos ].size = 0;
	stack[ attributeCheckInfo->stackPos ].attributeListPtr = attributeListPtr;
	stack[ attributeCheckInfo->stackPos++ ].attributeInfoPtr = attributeInfoPtr;

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int checkAttribute( INOUT_ARRAY( ATTRIBUTE_CHECK_INFO ) \
								ATTRIBUTE_CHECK_INFO *attributeCheckInfo );
						   /* Forward declaration for function */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int checkAttributeEntry( INOUT_ARRAY( ATTRIBUTE_CHECK_INFO ) \
									ATTRIBUTE_CHECK_INFO *attributeCheckInfo )
	{
	ATTRIBUTE_LIST *attributeListPtr = attributeCheckInfo->attributeListPtr;
	ATTRIBUTE_INFO *attributeInfoPtr = attributeCheckInfo->attributeInfoPtr;
	ATTRIBUTE_STACK *stack = attributeCheckInfo->stack;
	CRYPT_ATTRIBUTE_TYPE fieldID;

	assert( isWritePtr( attributeCheckInfo, \
						sizeof( ATTRIBUTE_CHECK_INFO ) ) );

	/* Determine the fieldID for the current attribute field.  Once we get 
	   to the end of an attribute list entry we may still run through this 
	   function multiple times with attributeListPtr set to NULL but 
	   attributeInfoPtr advancing on each step, see the comment in 
	   updateStackedInfo() for details */
	if( attributeListPtr == NULL || \
		attributeListPtr->fieldID == CRYPT_ATTRIBUTE_NONE )
		{
		/* If we've reached the end of the list of recognised attributes, 
		   use a non-ID that doesn't match any table entry */
		fieldID = CRYPT_IATTRIBUTE_LAST;
		}
	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, 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 */
				status = stackInfo( attributeCheckInfo, attributeListPtr,
									attributeInfoPtr );
				if( cryptStatusError( status ) )
					return( status );
				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;
			if( !( attributeInfoPtr->flags & FL_OPTIONAL ) && \
				attributeCheckInfo->attributeListPtr == attributeListPtr )
				{
				/* The subtyped field was non-optional but we failed to 
				   match anything in it against the current attribute list 
				   entry, there's a problem with the encoding table.  This 
				   check is used to catch situations where a subtyped field 
				   is used to encode a CHOICE for which each CHOICE field is 
				   optional but at least one component of the CHOICE must be 
				   present */
				retIntError();
				}
			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_ERRTYPE_NONE )
				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->intValue ) )
			{
			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, 
										 CRYPT_COMPLIANCELEVEL_STANDARD );
		if( attributeCheckInfo->stackPos > 0 )
			{
			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 that we want */
	if( attributeInfoPtr->flags & FL_IDENTIFIER )
		{
		BOOLEAN endOfAttributeField = FALSE;
		int status;

		status = checkComponentPresent( fieldID, &attributeInfoPtr );
		if( status == CRYPT_ERROR_NOTFOUND )
			{
			/* 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 );
			}
		if( cryptStatusError( status ) )
			return( status );

		/* Stack the position of the sequence start and the following OID */
		status = stackInfo( attributeCheckInfo, attributeListPtr, 
							attributeInfoPtr++ );
		if( cryptStatusOK( status ) )
			status = stackInfo( attributeCheckInfo, attributeListPtr, 
								attributeInfoPtr );
		if( cryptStatusError( status ) )
			return( status );

		/* 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 that
		   constitutes parameters for the OID, if this is present we stack it
		   as well */
		if( attributeInfoPtr[ 1 ].flags & FL_NONENCODING )
			{
			attributeInfoPtr++;
			status = stackInfo( attributeCheckInfo, attributeListPtr, 
								attributeInfoPtr );
			if( cryptStatusError( status ) )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -