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

📄 ext_rd.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
				status = processIdentifiedItem( stream, attributeListPtrPtr,
												flags, &setofStack, 
												&attributeInfoPtr, 
												errorLocus, errorType );
				if( cryptStatusError( status ) )
					{
					if( status == OK_SPECIAL )
						{
						/* We've switched to a new encoding table, continue
						   from there */
						status = CRYPT_OK;
						continue;
						}
					return( fieldErrorReturn( errorLocus, errorType, 
											  CRYPT_ERROR_BADDATA,
											  attributeInfoPtr->fieldID ) );
					}
				}
			}

		/* Subtyped field: Switch to the new encoding table */
		if( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )
			{
			attributeInfoPtr = switchToSubtype( attributeInfoPtr, 
												setofInfoPtr );
			ENSURES( attributeInfoPtr != NULL );
			}

		/* CHOICE (of object identifiers): Read a single OID from a
		   selection.
		   Identifier field: Read a sequence of one or more { oid, value }
		   fields and continue */
		if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE || \
			attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )
			{
			if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
				{
				const ATTRIBUTE_INFO *extraDataPtr = \
											attributeInfoPtr->extraData;
						/* Needed because ->extraData is read-only */

				status = readIdentifierFields( stream, attributeListPtrPtr,
							&extraDataPtr, flags, attributeInfoPtr->fieldID,
							errorLocus, errorType );
				}
			else
				{
				status = readIdentifierFields( stream, attributeListPtrPtr,
							&attributeInfoPtr, flags, CRYPT_ATTRIBUTE_NONE, 
							errorLocus, errorType );
				}
			if( cryptStatusError( status ) )
				{
				return( fieldErrorReturn( errorLocus, errorType,
										  CRYPT_ERROR_BADDATA,
										  attributeInfoPtr->fieldID ) );
				}
			if( setofInfoPtr->endPos > 0 )
				{
				/* Remember that we've seen an entry in the SET/SEQUENCE */
				setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
				}
			goto continueDecoding;
			}

		/* Non-encoding field: Skip it and continue */
		if( attributeInfoPtr->flags & FL_NONENCODING )
			{
			/* Read the data and continue.  We don't check its value or set
			   specific error information for reasons given under the SET-OF
			   handling code above (value check) and optional field code below
			   (error locus set) */
			TRACE_FIELDTYPE( attributeInfoPtr, setofStack.stackPos );
			status = readUniversal( stream );
			if( cryptStatusError( status ) )
				return( status );
			if( setofInfoPtr->endPos > 0 )
				{
				/* Remember that we've seen an entry in the SET/SEQUENCE */
				setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
				}
			goto continueDecoding;
			}

		/* Get the tag for the field */
		status = getFieldTag( stream, attributeInfoPtr, &tag );
		if( cryptStatusError( status ) )
			return( status );

		/* Optional field: Check whether it's present and if it isn't, move
		   on to the next field */
		if( ( attributeInfoPtr->flags & FL_OPTIONAL ) && \
			peekTag( stream ) != tag )
			{
			/* If it's a field with a default value, add that value.  This
			   isn't needed for cryptlib's own use since it knows the default
			   values for fields but can cause confusion for the caller if 
			   all fields in an attribute have default values because the
			   attribute will appear to disappear when it's read in as no
			   fields are ever added */
			if( attributeInfoPtr->flags & FL_DEFAULT )
				{
				CRYPT_ATTRIBUTE_TYPE dummy1;
				CRYPT_ERRTYPE_TYPE dummy2;
				const int value = ( int ) attributeInfoPtr->defaultValue;

				status = addAttributeField( attributeListPtrPtr,
							attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE,
							&value, CRYPT_UNUSED, flags, &dummy1, &dummy2 );
				if( cryptStatusError( status ) )
					{
					/* This is a field contributed from internal data so we
					   don't try and get an error locus or value for it
					   since this would only confuse the caller */
					return( CRYPT_ERROR_BADDATA );
					}
				}

			/* Skip to the end of the item and continue */
			status = findItemEnd( &attributeInfoPtr, 0 );
			if( cryptStatusError( status ) )
				return( status );
			goto continueDecoding;
			}

		/* Print a trace of what we're processing.  Everything before this
		   point does its own special-case tracing if required so we don't
		   trace before we get here to avoid displaying duplicate/
		   misleading information */
		TRACE_FIELDTYPE( attributeInfoPtr, setofStack.stackPos );

		/* Explicitly tagged field: Read the explicit wrapper and make sure
		   that it matches what we're expecting */
		if( attributeInfoPtr->flags & FL_EXPLICIT )
			{
			ENSURES( attributeInfoPtr->fieldEncodedType >= 0 && \
					 attributeInfoPtr->fieldEncodedType < MAX_TAG );
			ENSURES( tag == MAKE_CTAG( attributeInfoPtr->fieldEncodedType ) ); 
					 /* Always constructed */

			status = readConstructed( stream, NULL, 
									  attributeInfoPtr->fieldEncodedType );
			if( cryptStatusError( status ) )
				return( fieldErrorReturn( errorLocus, errorType, status,
										  attributeInfoPtr->fieldID ) );

			/* We've processed the explicit wrappper, we're now on the actual
			   tag */
			tag = attributeInfoPtr->fieldType;
			}

		/* Blob field or DN: We don't try and interpret blobs in any way, 
		   and DNs are a composite structure read as a complete unit by the 
		   lower-level code */
		if( attributeInfoPtr->fieldType == FIELDTYPE_BLOB || \
			attributeInfoPtr->fieldType == FIELDTYPE_DN )
			{
			status = readAttributeField( stream, attributeListPtrPtr,
										 attributeInfoPtr,
										 setofInfoPtr->subtypeParent,
										 flags | setofInfoPtr->inheritedFlags,
										 errorLocus, errorType );
			if( cryptStatusError( status ) )
				{
				/* Adding complex attributes such as DNs can return detailed
				   error codes that report the exact parameter that was wrong,
				   we don't need this much detail so we convert a parameter
				   error into a more general bad data status */
				return( fieldErrorReturn( errorLocus, errorType,
										  cryptArgError( status ) ? \
											CRYPT_ERROR_BADDATA : status,
										  attributeInfoPtr->fieldID ) );
				}
			if( setofInfoPtr->endPos > 0 )
				{
				/* Remember that we've seen an entry in the SET/SEQUENCE */
				setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
				}
			goto continueDecoding;
			}

		/* Standard field: Read the tag for the field and make sure that it
		   matches what we're expecting */
		if( peekTag( stream ) != tag )
			{
			return( fieldErrorReturn( errorLocus, errorType,
									  CRYPT_ERROR_BADDATA,
									  attributeInfoPtr->fieldID ) );
			}
		if( setofInfoPtr->endPos > 0 )
			{
			/* Remember that we've seen an entry in the SET/SEQUENCE */
			setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
			}

		/* SET/SET OF/SEQUENCE/SEQUENCE OF start: Record its end position,
		   stack the current processing state, and continue */
		if( attributeInfoPtr->fieldType == BER_SEQUENCE || \
			attributeInfoPtr->fieldType == BER_SET )
			{
			status = beginSetof( stream, &setofStack, attributeInfoPtr );
			if( cryptStatusError( status ) )
				return( fieldErrorReturn( errorLocus, errorType, status,
										  attributeInfoPtr->fieldID ) );
			setofInfoPtr = setofTOS( &setofStack );
			goto continueDecoding;
			}
		ENSURES( !( attributeInfoPtr->flags & FL_SETOF ) );

		/* We've checked the tag, skip it.  We do this at this level rather
		   than in readAttributeField() because it doesn't know about 
		   context-specific tagging requirements */
		status = readTag( stream );
		if( cryptStatusError( status ) )
			return( status );

		/* Standard field, read the field data */
		status = readAttributeField( stream, attributeListPtrPtr,
									 attributeInfoPtr,
									 setofInfoPtr->subtypeParent,
									 flags | setofInfoPtr->inheritedFlags,
									 errorLocus, errorType );
		if( cryptStatusError( status ) )
			{
			/* Adding invalid attribute data can return detailed error codes
			   that report the exact parameter that was wrong, we don't
			   need this much detail so we convert a parameter error into a
			   more general bad data status */
			return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
			}

		/* Move on to the next field */
continueDecoding:
		attributeContinues = ( attributeInfoPtr->flags & FL_MORE ) ? TRUE : FALSE;
		attributeInfoPtr++;

		/* If this is the end of the attribute encoding info but we're
		   inside a SET OF/SEQUENCE OF and there's more attribute data 
		   present, go back to the restart point and try again */
		if( !attributeContinues && setofInfoPtr->endPos > 0 && \
			stell( stream ) < setofInfoPtr->endPos )
			{
			/* If we require at least one entry in the SET OF/SEQUENCE OF 
			   but we haven't found one, this is an error */
			if( setofInfoPtr->flags & SETOF_FLAG_ISEMPTY )
				return( CRYPT_ERROR_BADDATA );

			/* If we haven't made any progress in processing the SET OF/
			   SEQUENCE OF then further iterations through the loop won't
			   make any difference, there's a bug in the decoder */
			ENSURES( stell( stream ) > setofInfoPtr->startPos );

			/* Retry from the restart point */
			ENSURES( ( setofInfoPtr->flags & SETOF_FLAG_RESTARTPOINT ) || \
					 setofInfoPtr->infoStart[ 1 ].fieldType == FIELDTYPE_IDENTIFIER );
			attributeInfoPtr = setofInfoPtr->infoStart + 1;
			attributeContinues = TRUE;
			}
		}
	while( ( attributeContinues || setofStack.stackPos > 1 ) && \
		   stell( stream ) < endPos && \
		   attributeFieldsProcessed++ < 256 );

	/* If we got stuck in a loop trying to decode an attribute, complain and 
	   exit.  This can happen in cases where there's a series of nested 
	   sequences of optional attributes, where we have to keep backtracking 
	   and trying again to try and find a match.  In this case it's possible
	   to construct certificate data that matches the first part of the 
	   optional data, but since the rest doesn't match we keep having to 
	   restart (imagine an LL(1) parser trying to handle a non-LL(1) 
	   grammar).
	   
	   At this point we could have encountered either a certificate-parsing 
	   error or a CRYPT_ERROR_INTERNAL internal error, since we can't tell 
	   without human intervention we treat it as a certificate error rather 
	   than throwing a retIntError() exception */
	if( attributeFieldsProcessed >= 256 )
		{
		assert( DEBUG_WARN );
		return( CRYPT_ERROR_BADDATA );
		}

	/* Handle the special case of (a) the encoded data ending but fields with
	   default values being present or (b) the encoded data continuing but no 
	   more decoding information being present */
	if( attributeContinues )
		{
		/* If there are default fields to follow, add the default value - see
		   the comment on the handling of default fields above.  For now we
		   only add the first field since the only attributes where this
		   case can occur have a single default value as the next possible
		   entry, burrowing down further causes complications due to default
		   values present in optional sequences.  As usual we don't set any
		   specific error information for the default fields */
		if( attributeInfoPtr->flags & FL_DEFAULT )
			{
			CRYPT_ATTRIBUTE_TYPE dummy1;
			CRYPT_ERRTYPE_TYPE dummy2;
			const int value = ( int ) attributeInfoPtr->defaultValue;

			status = addAttributeField( attributeListPtrPtr,
						attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE,
						&value, CRYPT_UNUSED, flags, &dummy1, &dummy2 );
			if( cryptStatusError( status ) )
				return( status );
			}
		}
	else
		{
		int iterationCount;
		
		/* Some attributes have a SEQUENCE OF fields of no great use (e.g.
		   Microsoft's extensive crlDistributionPoints lists providing
		   redundant pointers to the same inaccessible site-internal
		   servers, although these are already handled above), if there's
		   any extraneous data left we just skip it */
		for( iterationCount = 0;
			 stell( stream ) < endPos && cryptStatusOK( status ) && \
				iterationCount < FAILSAFE_ITERATIONS_LARGE;
			 iterationCount++ )
			{
			assert( DEBUG_WARN );
			status = readUniversal( stream );
			}
		ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
		}
	return( status );
	}

/****************************************************************************
*																			*
*						Attribute Collection Read Routines					*
*																			*
****************************************************************************/

/* Read the certificate object-specific wrapper for a set of attributes */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readAttributeWrapper( INOUT STREAM *stream, 
								 OUT_LENGTH_Z int *lengthPtr, 
								 IN_ENUM_OPT( CRYPT_CERTTYPE ) \
									const CRYPT_CERTTYPE_TYPE type,
								 IN_LENGTH const int attributeLength )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( lengthPtr, sizeof( int ) ) );

⌨️ 快捷键说明

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