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

📄 certexrw.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:

		/* 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_IA5 || \
		attributeInfoPtr->fieldType == BER_STRING_ISO646 || \
		attributeInfoPtr->fieldType == BER_STRING_NUMERIC || \
		attributeInfoPtr->fieldType == BER_STRING_PRINTABLE || \
		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 */
		return( addAttributeField( attributeListPtrPtr, fieldID, subFieldID, 
								   buffer, length, flags, 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 ];

		status = readRawObjectData( stream, oid + 1, &length, 
									MAX_OID_SIZE - 1 );
		if( cryptStatusError( status ) )
			return( fieldErrorReturn( errorLocus, errorType, status,
									  attributeInfoPtr->fieldID ) );
		oid[ 0 ] = BER_OBJECT_IDENTIFIER;	/* Add skipped tag */
		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 = readDNTag( stream, &dnPtr,
							( attributeInfoPtr->fieldEncodedType ) ? \
							NO_TAG : DEFAULT_TAG );
		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 );
			}

		return( CRYPT_OK );
		}

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

/* 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 )
	{
	const ATTRIBUTE_INFO *savedAttributeInfoPtr = NULL;
	const ATTRIBUTE_INFO *setofItemStartPtr = NULL;
	const int endPos = ( int ) stell( stream ) + attributeLength;
	CRYPT_ATTRIBUTE_TYPE subtypeParent = CRYPT_ATTRIBUTE_NONE;
	BOOLEAN attributeContinues = TRUE, isVariableSet;
	int flags = criticalFlag ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE;
	int inheritedFlags = ATTR_FLAG_NONE;
	int setEndPos = 0, setEndEOC = 0, savedSetEndPos = 0;

	assert( isWritePtr( attributeListPtrPtr, ATTRIBUTE_LIST * ) );
	assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );
	assert( criticalFlag == TRUE || criticalFlag == FALSE );
	assert( attributeLength >= 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, status;

		/* Subtyped field: Switch to the new encoding table */
		if( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )
			{
			subtypeParent = attributeInfoPtr->fieldID;
			inheritedFlags = ( attributeInfoPtr->flags & FL_MULTIVALUED ) ? \
							 ATTR_FLAG_MULTIVALUED : ATTR_FLAG_NONE;

			/* Push the current parse state and switch to the new state */
			savedAttributeInfoPtr = attributeInfoPtr;
			attributeInfoPtr = ( ATTRIBUTE_INFO * ) attributeInfoPtr->extraData;
			savedSetEndPos = setEndPos;
			setEndPos = 0;
			}

		/* CHOICE (of object identifiers): Read a single OID */
		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 );
			if( cryptStatusError( status ) )
				return( status );
			goto continueDecoding;
			}

		/* SET OF/SEQUENCE OF: Record its length and end position and
		   continue.  If we're processing a SET OF/SEQUENCE OF, check for the
		   end of an item or the end of the collection of items */
		if( attributeInfoPtr->flags & ( FL_SETOF_FIXED | FL_SETOF_VARIABLE ) )
			{
			void *objectPtr = sMemBufPtr( stream );
			int setofLength;

			assert( !attributeInfoPtr->fieldEncodedType && \
					!( attributeInfoPtr->flags & FL_EXPLICIT ) );

			/* Determine the length and start position of the set of items.
			   Some broken Verisign certs suddenly break into BER inside the
			   cert policy extension so if the length evaluates to zero we
			   have to determine it by burrowing into the ASN.1 */
			if( attributeInfoPtr->fieldType == BER_SET )
				status = readSet( stream, &setofLength );
			else
				status = readSequence( stream, &setofLength );
			if( cryptStatusOK( status ) && !setofLength )
				{
				/* Get the overall length without the tag + indef.length */
				status = setofLength = \
					getObjectLength( objectPtr, sMemDataLeft( stream ) ) - 2;
				setEndEOC = 2;	/* Two bytes of EOC at end of object */
				}
			setEndPos = ( int ) stell( stream ) + setofLength;
			if( cryptStatusError( status ) )
				return( fieldErrorReturn( errorLocus, errorType, status,
										  attributeInfoPtr->fieldID ) );

			/* Remember where the first item in the SET/SEQUENCE starts.  We
			   use this as a restart point when we're parsing the next item
			   in the SET/SEQUENCE OF items using findIdentifiedItem() for a
			   choice of fixed items) or a general read (for a collection of
			   variable items) */
			isVariableSet = ( attributeInfoPtr->flags & FL_SETOF_VARIABLE ) ? \
							TRUE : FALSE;
			setofItemStartPtr = ++attributeInfoPtr;
			continue;
			}
		if( setEndPos )
			{
			/* If we've reached the end of the collection of items, exit (at
			   the moment these items always occur at the end of an attribute,
			   this may need to be changed later) */
			if( stell( stream ) >= setEndPos - setEndEOC )
				{
				/* If the extension drops into BER, make sure the EOC is
				   present */
				if( setEndEOC && !checkEOC( stream ) )
					return( CRYPT_ERROR_BADDATA );
				break;
				}

			/* If we're looking for a new item, find the table entry which 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 (ie on the next item
			   flagged as an identifier) or at the end of the attribute (ie on
			   the start of the next attribute) */
			if( setEndPos && ( !( attributeInfoPtr[ -1 ].flags & FL_MORE ) ||
							   attributeInfoPtr->flags & FL_IDENTIFIER ) )
				{
				attributeInfoPtr = findIdentifiedItem( stream, setofItemStartPtr );
				if( attributeInfoPtr == NULL )
					return( fieldErrorReturn( errorLocus, errorType, 
											  CRYPT_ERROR_BADDATA,
											  attributeInfoPtr->fieldID ) );

				/* 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.  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 */
						status = addAttributeField( attributeListPtrPtr,
							attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE,
							&dummy, CRYPT_UNUSED, flags, errorLocus, 
							errorType );
						if( status == CRYPT_ERROR_INITED )
							status = CRYPT_OK;
						if( cryptStatusError( status ) )
							return( status );
						}

					/* Reset the attribute info position in preparation for
					   the next value and continue */
					attributeInfoPtr = setofItemStartPtr;
					continue;
					}
				}
			}

		/* Identifier field: We've reached the first of a sequence of
		   possible alternatives, read the sequence of one or more fields and
		   continue */
		if( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )
			{
			status = readIdentifierFields( stream, attributeListPtrPtr,
								&attributeInfoPtr, flags, 
								CRYPT_ATTRIBUTE_NONE, errorLocus, errorType );
			if( cryptStatusError( status ) )
				return( status );
			goto continueDecoding;
			}

		/* Non-encoding field: Check that it matches the required value and
		   continue */
		if( attributeInfoPtr->flags & FL_NONENCODING )
			{
			BYTE data[ 64 ];
			int dataLength;

			/* 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) */
			status = readRawObject( stream, data, &dataLength, 64, CRYPT_UNUSED );
			if( cryptStatusError( status ) )
				return( status );

			goto continueDecoding;
			}

		/* Extract various pieces of information from the attribute field
		   definition */
		isTagged = ( attributeInfoPtr->fieldEncodedType ) ? TRUE : FALSE;
		tag = ( isTagged ) ? attributeInfoPtr->fieldEncodedType : \
							 attributeInfoPtr->fieldType;
		if( isTagged && ( attributeInfoPtr->fieldType == BER_SEQUENCE ||
						  attributeInfoPtr->fieldType == BER_SET ||
						  attributeInfoPtr->fieldType == FIELDTYPE_DN ||
						  ( attributeInfoPtr->flags & FL_EXPLICIT ) ) )
			/* If it's an implictly tagged sequence/set then it's constructed */
			tag |= BER_CONSTRUCTED;

		/* 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.  Since this is a field contributed from
			   internal data, we don't try and get an error locus or value 
			   for it since this would only confuse the caller */
			if( attributeInfoPtr->flags & FL_DEFAULT )
				{
				const int value = ( int ) attributeInfoPtr->defaultValue;

				status = addAttributeField( attributeListPtrPtr,
							attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE, 
							&value, CRYPT_UNUSED, flags, NULL, NULL );
				if( cryptStatusError( status ) )
					return( status );
				}

			/* Skip to the end of the item and continue */
			attributeInfoPtr = findItemEnd( attributeInfoPtr, 0 );

⌨️ 快捷键说明

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