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

📄 certexrd.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* Read the data as appropriate */
		switch( attributeInfoPtr->fieldType )
			{
			case BER_BITSTRING:
				status = readBitStringData( stream, &value );
				break;

			case BER_BOOLEAN:
				status = readBooleanData( stream, &boolean );
				value = boolean;
				break;

			case BER_ENUMERATED:
				status = readEnumeratedData( stream, &value );
				break;

			case BER_INTEGER:
				status = readShortIntegerData( stream, &longValue );
				value = ( int ) longValue;
				break;

			case BER_NULL:
				/* NULL values have no associated data so we explicitly set
				   the value to CRYPT_UNUSED to ensure that this is returned
				   on any attempt to read it */
				value = CRYPT_UNUSED;
				break;

			default:
				assert( NOTREACHED );
				return( CRYPT_ERROR );
			}
		if( cryptStatusError( status ) )
			return( fieldErrorReturn( errorLocus, errorType, status,
									  attributeInfoPtr->fieldID ) );

		/* Add the data for this attribute field */
		return( addAttributeField( attributeListPtrPtr, fieldID, subFieldID,
								   &value, CRYPT_UNUSED, flags, errorLocus,
								   errorType ) );
		}
	if( attributeInfoPtr->fieldType == BER_TIME_GENERALIZED || \
		attributeInfoPtr->fieldType == BER_TIME_UTC )
		{
		time_t timeVal;

		if( attributeInfoPtr->fieldType == BER_TIME_GENERALIZED )
			status = readGeneralizedTimeData( stream, &timeVal );
		else
			status = readUTCTimeData( stream, &timeVal );
		if( cryptStatusError( status ) )
			return( fieldErrorReturn( errorLocus, errorType, status,
									  attributeInfoPtr->fieldID ) );

		/* Add the data for this attribute field */
		return( addAttributeField( attributeListPtrPtr, fieldID, subFieldID,
								   &timeVal, sizeof( time_t ), flags,
								   errorLocus, errorType ) );
		}

	/* If it's a string type or a blob, read it in as a blob (the only
	   difference being that for a true blob we read the tag + length as
	   well) */
	if( attributeInfoPtr->fieldType == BER_STRING_BMP || \
		attributeInfoPtr->fieldType == BER_STRING_IA5 || \
		attributeInfoPtr->fieldType == BER_STRING_ISO646 || \
		attributeInfoPtr->fieldType == BER_STRING_NUMERIC || \
		attributeInfoPtr->fieldType == BER_STRING_PRINTABLE || \
		attributeInfoPtr->fieldType == BER_STRING_T61 || \
		attributeInfoPtr->fieldType == BER_STRING_UTF8 || \
		attributeInfoPtr->fieldType == BER_OCTETSTRING || \
		attributeInfoPtr->fieldType == FIELDTYPE_BLOB )
		{
		BYTE buffer[ 256 ];

		/* Read in the string to a maximum length of 256 bytes.  Anything
		   longer is quietly truncated, strings in certs shouldn't be this
		   long anyway */
		if( attributeInfoPtr->fieldType == FIELDTYPE_BLOB )
			status = readRawObjectTag( stream, buffer, &length, 256, CRYPT_UNUSED );
		else
			status = readOctetStringData( stream, buffer, &length, 256 );
		if( cryptStatusError( status ) )
			return( fieldErrorReturn( errorLocus, errorType, status,
									  attributeInfoPtr->fieldID ) );

		/* There are enough broken certs out there with enormously long
		   disclaimers in the cert policy explicit text field that we
		   have to specifically check for them here and truncate the text
		   at a valid length in order to get it past the extension
		   validity checking code */
		if( fieldID == CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT && \
			length > 200 )
			length = 200;

		/* Add the data for this attribute field, setting the payload-blob
		   flag to disable type-checking of the payload data so users can
		   cram any old rubbish into the strings */
		return( addAttributeField( attributeListPtrPtr, fieldID, subFieldID,
								   buffer, length, flags | ATTR_FLAG_BLOB_PAYLOAD,
								   errorLocus, errorType ) );
		}

	/* If it's an OID, we need to reassemble the entire OID since this is the
	   form expected by addAttributeField() */
	if( attributeInfoPtr->fieldType == BER_OBJECT_IDENTIFIER )
		{
		BYTE oid[ MAX_OID_SIZE ];

		oid[ 0 ] = BER_OBJECT_IDENTIFIER;	/* Add skipped tag */
		status = readRawObjectData( stream, oid + 1, &length,
									MAX_OID_SIZE - 1 );
		if( cryptStatusError( status ) )
			return( fieldErrorReturn( errorLocus, errorType, status,
									  attributeInfoPtr->fieldID ) );
		return( addAttributeField( attributeListPtrPtr, fieldID, subFieldID,
								   oid, length + 1, flags, errorLocus,
								   errorType ) );
		}

	/* If it's a special-case field, read it */
	if( attributeInfoPtr->fieldType == FIELDTYPE_DN )
		{
		void *dnPtr = NULL;

		/* Read the DN */
		status = readDN( stream, &dnPtr );
		if( cryptStatusError( status ) )
			return( fieldErrorReturn( errorLocus, errorType, status,
									  attributeInfoPtr->fieldID ) );

		/* Some buggy certs can include zero-length DNs, which we skip */
		if( dnPtr == NULL )
			return( CRYPT_OK );

		/* We're being asked to instantiate the field containing the DN,
		   create the attribute field and fill in the DN value */
		status = addAttributeField( attributeListPtrPtr, fieldID, subFieldID,
									dnPtr, CRYPT_UNUSED, flags, errorLocus,
									errorType );
		if( cryptStatusError( status ) )
			deleteDN( &dnPtr );
		return( status );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

/* When we're processing SETs/SEQUENCEs (generically referred to as a SET
   OF), we need to maintain a stack of state information in case we
   encounter a nested SET OF.  The following code implements the state
   stack */

#define SETOF_STATE_STACKSIZE	16

typedef struct {
	const ATTRIBUTE_INFO *infoStart;	/* Start of SET OF attribute info */
	int endPos, endEOC;		/* End position of SET OF and optional EOC */
	CRYPT_ATTRIBUTE_TYPE subtypeParent;	/* Parent type if this is subtyped */
	int inheritedFlags;		/* Flags inherited from parent if subtyped */
	BOOLEAN restartPoint;	/* Info is a SET OF (rather than SET) */
	BOOLEAN subTyped;		/* SET ends on a subtyped value */
	} SETOF_STATE_INFO;

static SETOF_STATE_INFO *stackSetofState( SETOF_STATE_INFO *setofStack,
										  int *stackPos )
	{
	const int newPos = *stackPos + 1;

	/* Increment the stack pointer and make sure we don't overflow */
	if( newPos >= SETOF_STATE_STACKSIZE )
		{
		assert( NOTREACHED );
		return( &setofStack[ 0 ] );
		}
	*stackPos = newPos;

	/* Initialise the new entry */
	memset( &setofStack[ newPos ], 0, sizeof( SETOF_STATE_INFO ) );
	return( &setofStack[ newPos ] );
	}

static SETOF_STATE_INFO *unstackSetofState( SETOF_STATE_INFO *setofStack,
											int *stackPos )
	{
	const int newPos = *stackPos - 1;

	if( newPos < 0 )
		{
		assert( NOTREACHED );
		return( &setofStack[ 0 ] );
		}
	*stackPos = newPos;
	return( &setofStack[ newPos ] );
	}

/* Read an attribute */

static int readAttribute( STREAM *stream, ATTRIBUTE_LIST **attributeListPtrPtr,
			const ATTRIBUTE_INFO *attributeInfoPtr, const int attributeLength,
			const BOOLEAN criticalFlag, CRYPT_ATTRIBUTE_TYPE *errorLocus,
			CRYPT_ERRTYPE_TYPE *errorType )
	{
	SETOF_STATE_INFO setofStack[ SETOF_STATE_STACKSIZE ];
	SETOF_STATE_INFO *setofInfoPtr;
	const int endPos = stell( stream ) + attributeLength;
	BOOLEAN attributeContinues = TRUE;
	int flags = criticalFlag ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE;
	int setofStackPos = 0, status = CRYPT_OK;

	assert( isWritePtr( attributeListPtrPtr, ATTRIBUTE_LIST * ) );
	assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );
	assert( criticalFlag == TRUE || criticalFlag == FALSE );
	assert( attributeLength >= 0 );

	/* Clear the top of the SET OF state stack.  This entry is always all-
	   zero to represent an empty stack */
	memset( &setofStack[ 0 ], 0, sizeof( SETOF_STATE_INFO ) );
	setofInfoPtr = &setofStack[ 0 ];

	/* Process each field in the attribute.  This is a simple FSM driven by
	   the encoding table and the data we encounter.  The various states and
	   associated actions are indicated by the comment tags */
	do
		{
		BOOLEAN isTagged;
		int tag;

		/* Inside a SET/SET OF/SEQUENCE/SEQUENCE OF: Check for the end of the
		   item/collection of items.  This must be the first action taken
		   since reaching the end of a SET/SEQUENCE pre-empts all other
		   parsing actions */
		if( setofInfoPtr->endPos > 0 )
			{
			const ATTRIBUTE_INFO *oldAttributeInfoPtr = attributeInfoPtr;

			/* If we've reached the end of the collection of items, exit */
			while( setofStackPos > 0 && \
				   stell( stream ) >= setofInfoPtr->endPos )
				{
#if 0		/* 22/11/03 Removed since these Verisign certs have now expired */
				/* If the extension drops into BER, make sure that the EOC
				   is present */
				if( setofInfoPtr->endEOC > 0 && checkEOC( stream ) != TRUE )
					return( CRYPT_ERROR_BADDATA );
#endif /* 0 */

				/* Pop one level of parse state.  If it's a restart point
				   (SET OF/SEQUENCE OF), restart from here */
				if( !setofInfoPtr->restartPoint || \
					stell( stream ) >= setofInfoPtr->endPos )
					/* It's a straight SET/SEQUENCE, find what follows it */
					attributeInfoPtr = findItemEnd( setofInfoPtr->infoStart, 0 );
				else
					/* It's a SET OF/SEQUENCE OF and there are more entries
					   present, restart from the start of the SET OF */
					attributeInfoPtr = setofInfoPtr->infoStart;
				setofInfoPtr = unstackSetofState( setofStack,
												  &setofStackPos );

				assert( setofInfoPtr->endPos > 0 && \
						setofInfoPtr->endPos < 65536L );
				}
			if( attributeInfoPtr != oldAttributeInfoPtr )
				goto continueDecoding;

			/* If we're looking for a new item, find the table entry that it
			   corresponds to.  This takes a pointer to the start of a set of
			   SEQUENCE { type, value } entries and returns a pointer to the
			   appropriate value entry.

			   The test for the start of a new item is a bit complex since we
			   could be at the end of the previous item (i.e. on the next item
			   flagged as an identifier) or at the end of the attribute (i.e.
			   on the start of the next attribute) */
			if( !( attributeInfoPtr[ -1 ].flags & FL_MORE ) || \
				attributeInfoPtr->flags & FL_IDENTIFIER )
				{
				const CRYPT_ATTRIBUTE_TYPE oldFieldID = \
									attributeInfoPtr->fieldID;

				/* Search for the identified item from the start of the
				   set of items.  The 0-th value is the SET OF/SEQUENCE OF,
				   so we start the search at the next entry which is the
				   first FL_IDENTIFIER */
				assert( setofInfoPtr->infoStart->flags & FL_SETOF );
				attributeInfoPtr = findIdentifiedItem( stream,
											setofInfoPtr->infoStart + 1 );
				if( attributeInfoPtr == NULL )
					return( fieldErrorReturn( errorLocus, errorType,
											  CRYPT_ERROR_BADDATA,
											  oldFieldID ) );

				/* If it's a subtyped field, continue from a new encoding
				   table */
				if( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )
					continue;

				/* If the { type, value } pair has a fixed value then the
				   information being conveyed is its presence, not its
				   contents, so we add an attribute corresponding to its ID
				   and continue.  The addition of the attribute is a bit
				   tricky, some of the fixed type-and-value pairs can have
				   multiple entries denoting things like { algorithm, weak
				   key }, { algorithm, average key }, { algorithm, strong
				   key }, however all we're interested in is the strong key
				   so we ignore the value and only use the type (in his ordo 
				   est ordinem non servare).  Since the same type can be 
				   present multiple times (with different { value }s), we 
				   ignore data duplicate errors and continue */
				if( attributeInfoPtr->flags & FL_NONENCODING )
					{
					const int dummy = CRYPT_UNUSED;

					/* If it's a blob field type, we've ended up at a
					   generic catch-any value and can't do much with it */
					if( attributeInfoPtr->fieldType != FIELDTYPE_BLOB )
						{
						/* Add the field type, discarding warnings about dups */

⌨️ 快捷键说明

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