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

📄 ext_rd.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	{
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	REQUIRES( cryptStatusError( status ) );
	REQUIRES( fieldID > CRYPT_ATTRIBUTE_NONE && \
			  fieldID < CRYPT_IATTRIBUTE_LAST );

	/* Since some fields are internal-use only (e.g. meaningless blob data,
	   version numbers, and other paraphernalia) we only set the locus if
	   it has a meaningful value */
	*errorLocus = ( fieldID > CRYPT_CERTINFO_FIRST && \
					fieldID < CRYPT_CERTINFO_LAST ) ? \
				  fieldID : CRYPT_ATTRIBUTE_NONE;
	*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
	return( status );
	}

/* Switch from the main encoding table to a subtype encoding table */

CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \
static ATTRIBUTE_INFO *switchToSubtype( const ATTRIBUTE_INFO *attributeInfoPtr,
										INOUT SETOF_STATE_INFO *setofInfoPtr )
	{
	assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
	assert( isReadPtr( attributeInfoPtr->extraData, 
					   sizeof( ATTRIBUTE_INFO ) ) );
	assert( isWritePtr( setofInfoPtr, sizeof( SETOF_STATE_INFO ) ) );

	REQUIRES_N( attributeInfoPtr->extraData != NULL );

	/* Record the subtype parent information */
	setofInfoPtr->subtypeParent = attributeInfoPtr->fieldID;
	setofInfoPtr->inheritedFlags = \
							( attributeInfoPtr->flags & FL_MULTIVALUED ) ? \
								ATTR_FLAG_MULTIVALUED : ATTR_FLAG_NONE;

	/* If the subtype is being used to process a list of { ... OPTIONAL, 
	   ... OPTIONAL } and at least one entry must be present, remember 
	   that we haven't seen any entries yet */
	if( attributeInfoPtr->flags & FL_NONEMPTY )
		setofInfoPtr->flags |= SETOF_FLAG_ISEMPTY;

	/* If the subtype ends once the current SET/SEQUENCE ends, remember this 
	   so that we return to the main type when appropriate */
	if( ( attributeInfoPtr->flags & FL_SEQEND_MASK ) || \
		!( attributeInfoPtr->flags & FL_MORE ) )
		setofInfoPtr->flags |= SETOF_FLAG_SUBTYPED;

	/* Switch to the subtype encoding table */
	return( ( ATTRIBUTE_INFO * ) attributeInfoPtr->extraData );
	}

/* Read the contents of an attribute field.  This uses the readXXXData() 
   variants of the read functions because the field that we're reading may 
   be tagged so we process the tag at a higher level and only read the 
   contents here */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \
static int readAttributeField( INOUT STREAM *stream, 
							   /*?*/ ATTRIBUTE_LIST **attributeListPtrPtr,
							   const ATTRIBUTE_INFO *attributeInfoPtr,
							   IN_ATTRIBUTE_OPT \
									const CRYPT_ATTRIBUTE_TYPE subtypeParent, 
							   IN_FLAGS( ATTR ) const int flags, 
							   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
									CRYPT_ATTRIBUTE_TYPE *errorLocus,
							   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
									CRYPT_ERRTYPE_TYPE *errorType )
	{
	CRYPT_ATTRIBUTE_TYPE fieldID, subFieldID;
	const int fieldType = attributeInfoPtr->fieldType;
	int length, status = CRYPT_OK;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
	assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	REQUIRES( subtypeParent >= CRYPT_ATTRIBUTE_NONE && \
			  subtypeParent < CRYPT_ATTRIBUTE_LAST );
assert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_CRITICAL | ATTR_FLAG_MULTIVALUED ) ) == 0 );
	REQUIRES( flags >= ATTR_FLAG_NONE && flags <= ATTR_FLAG_MAX );
	REQUIRES( !( flags & ATTR_FLAG_INVALID ) );

	/* Set up the field identifiers depending on whether it's a normal field
	   or a subfield of a parent field */
	if( subtypeParent == CRYPT_ATTRIBUTE_NONE )
		{
		fieldID = attributeInfoPtr->fieldID;
		subFieldID = CRYPT_ATTRIBUTE_NONE;
		}
	else
		{
		fieldID = subtypeParent;
		subFieldID = attributeInfoPtr->fieldID;
		}

	/* Read the field as appropriate */
	switch( fieldType )
		{
		case BER_INTEGER:
		case BER_ENUMERATED:
		case BER_BITSTRING:
		case BER_BOOLEAN:
		case BER_NULL:
			{
			BOOLEAN boolean;
			long longValue;
			int value;

			/* Read the data as appropriate */
			switch( 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:
					retIntError();
				}
			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 ) );
			}

		case BER_TIME_GENERALIZED:
		case BER_TIME_UTC:
			{
			time_t timeVal;

			if( 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 ) );
			}

		case BER_STRING_BMP:
		case BER_STRING_IA5:
		case BER_STRING_ISO646:
		case BER_STRING_NUMERIC:
		case BER_STRING_PRINTABLE:
		case BER_STRING_T61:
		case BER_STRING_UTF8:
		case BER_OCTETSTRING:
		case FIELDTYPE_BLOB:
		case FIELDTYPE_DISPLAYSTRING:
			{
			/* 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) */
			BYTE buffer[ 256 + 8 ];

			/* Read in the string to a maximum length of 256 bytes */
			if( fieldType == FIELDTYPE_BLOB )
				{
				const int tag = peekTag( stream );
				if( cryptStatusError( tag ) )
					{
					return( fieldErrorReturn( errorLocus, errorType, tag,
											  attributeInfoPtr->fieldID ) );
					}

				/* Reading in blob fields is somewhat difficult since these
				   are typically used to read SET/SEQUENCE OF kitchensink
				   values and so won't have a consistent tag that we can pass
				   to readRawObject().  To get around this we peek ahead into
				   the stream to get the tag and then pass that down to 
				   readRawObject().  Note that this requires that the blob 
				   have an internal structure (with its own { tag, length }
				   data) since the caller has already stripped off the tag
				   and length */
				status = readRawObject( stream, buffer, 256, &length, tag );
				}
			else
				{
				status = readOctetStringData( stream, buffer, &length, \
											  1, 256 );
				}
			if( cryptStatusError( status ) )
				return( fieldErrorReturn( errorLocus, errorType, status,
										  attributeInfoPtr->fieldID ) );

			/* There are enough broken certificates out there with 
			   enormously long disclaimers in the certificate 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 ) );
			}

		case BER_OBJECT_IDENTIFIER:
			{
			BYTE oid[ MAX_OID_SIZE + 8 ];

			/* If it's an OID, we need to reassemble the entire OID since 
			   this is the form expected by addAttributeField() */
			oid[ 0 ] = BER_OBJECT_IDENTIFIER;	/* Add skipped tag */
			status = readEncodedOID( stream, oid  + 1, MAX_OID_SIZE - 1, 
									 &length, NO_TAG );
			if( cryptStatusError( status ) )
				return( fieldErrorReturn( errorLocus, errorType, status,
										  attributeInfoPtr->fieldID ) );
			return( addAttributeField( attributeListPtrPtr, fieldID, 
									   subFieldID, oid, length + 1, flags, 
									   errorLocus, errorType ) );
			}

		case FIELDTYPE_DN:
			{
			void *dnPtr = NULL;

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

			/* Some buggy certificates 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 );
			}
		}

	retIntError();
	}

/* Read an attribute */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \
static int readAttribute( INOUT STREAM *stream, 
						  /*?*/ ATTRIBUTE_LIST **attributeListPtrPtr,
						  const ATTRIBUTE_INFO *attributeInfoPtr, 
						  IN_LENGTH_Z const int attributeLength, 
						  const BOOLEAN criticalFlag, 
						  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
							CRYPT_ATTRIBUTE_TYPE *errorLocus,
						  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
							CRYPT_ERRTYPE_TYPE *errorType )
	{
	SETOF_STACK setofStack;
	SETOF_STATE_INFO *setofInfoPtr;
	const int endPos = stell( stream ) + attributeLength;
	BOOLEAN attributeContinues = TRUE;
	int flags = criticalFlag ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE;
	int attributeFieldsProcessed = 0, status = CRYPT_OK;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
	assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
	
	REQUIRES( attributeLength >= 0 && attributeLength < MAX_INTLENGTH );

	/* Initialise the SET OF state stack */
	setofStackInit( &setofStack );
	setofInfoPtr = setofTOS( &setofStack );

	/* Process each field in the attribute.  This is a simple FSM driven by
	   the encoding table and the data that we encounter.  The various 
	   states and associated actions are indicated by the comment tags */
	do
		{
		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 )
			{
			/* If we've reached the end of the collection of items, exit */
			status = checkSetofEnd( stream, &setofStack, &attributeInfoPtr );
			if( cryptStatusError( status ) && status != OK_SPECIAL )
				return( status );
			setofInfoPtr = setofTOS( &setofStack );
			if( status == OK_SPECIAL )
				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 ) )
				{

⌨️ 快捷键说明

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