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

📄 certechk.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 2 页
字号:
		{
		/* 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 */
				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, where each CHOICE field is optional but 
				   at least one component of the CHOICE must be present */
				assert( NOTREACHED );
				return( CRYPT_ERROR_FAILED );
				}
			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->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 );
		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;
		int status;

		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 */
		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 ) )
				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 */
			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 */
		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 */

static int checkAttribute( ATTRIBUTE_CHECK_INFO *attributeCheckInfo )
	{
	ATTRIBUTE_LIST *restartEntry = NULL;
	ATTRIBUTE_INFO *restartPoint;
	int restartStackPos, iterationCount = 0;
	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;

		/* Sanity check to make sure we don't fall off the end of the 
		   table */
		if( attributeCheckInfo->attributeInfoPtr->fieldID == CRYPT_ERROR )
			{
			assert( NOTREACHED );
			return( CRYPT_ERROR_OVERFLOW );
			}

		/* 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 */
			updateStackedInfo( attributeCheckInfo->stack,
				&attributeCheckInfo->stackPos,
				decodeNestingLevel( attributeCheckInfo->attributeInfoPtr->flags ),
				TRUE );
			}

		/* 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 certs which contain
			   them */
			assert( NOTREACHED );
#endif /* 0 */

			/* Restart at the table entry for the previous instance of the 
			   item, and adjust the stack to match */
			restartEntry = NULL;
			attributeCheckInfo->attributeInfoPtr = restartPoint;
			attributeContinues = TRUE;
			if( attributeCheckInfo->stackPos > restartStackPos )
				updateStackedInfo( attributeCheckInfo->stack,
							&attributeCheckInfo->stackPos,
							attributeCheckInfo->stackPos - restartStackPos,
							TRUE );

			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++ < 1000 );
	attributeCheckInfo->choiceState = CHOICE_NONE;

	/* Safety check in case of an invalid encoding table */
	if( iterationCount >= 1000 )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_OVERFLOW );
		}
	
	/* 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 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;
		 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->fieldID != CRYPT_ERROR )
			attributeCheckInfo.attributeInfoPtr++;
		if( attributeCheckInfo.attributeInfoPtr->fieldID == CRYPT_ERROR )
			{
			/* Safety check in case of an invalid encoding table */
			assert( NOTREACHED );
			return( CRYPT_ERROR_OVERFLOW );
			}
		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 + -