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

📄 ext_rd.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
			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 ];

			/* Read in the string to a maximum length of 256 bytes */
			if( 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 ) );
			}

		case BER_OBJECT_IDENTIFIER:
			{
			BYTE oid[ MAX_OID_SIZE ];

			/* 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 = 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 ) );
			}

		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 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 );
			}
		
		default:
			assert( NOTREACHED );
			return( CRYPT_ERROR );
		}

	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 )
	{
	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 iterationCount = 0, status = CRYPT_OK;

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

	/* 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 ) )
				return( status );
			setofInfoPtr = setofTOS( &setofStack );
			if( status )
				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 )
				{
				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 );

		/* 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: 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) */
			TRACE_FIELDTYPE( attributeInfoPtr, setofStack.stackPos );
			status = readRawObject( stream, data, &dataLength, 64, CRYPT_UNUSED );
			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 */
		tag = getFieldTag( stream, attributeInfoPtr );

		/* 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 )
				{
				const int value = ( int ) attributeInfoPtr->defaultValue;

				status = addAttributeField( attributeListPtrPtr,
							attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE,
							&value, CRYPT_UNUSED, flags, NULL, NULL );
				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 )
			{
			assert( attributeInfoPtr->fieldEncodedType > 0 );
			assert( MAKE_CTAG( tag ) == tag );	/* Always constructed */
			status = readConstructed( stream, NULL, tag );
			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, 
								 errorLocus, errorType );
			if( cryptStatusError( status ) )
				return( fieldErrorReturn( errorLocus, errorType, status,
										  attributeInfoPtr->fieldID ) );
			setofInfoPtr = setofTOS( &setofStack );
			goto continueDecoding;
			}
		assert( !( 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 */
		readTag( stream );

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

			/* Retry from the restart point */
			assert( ( setofInfoPtr->flags & SETOF_FLAG_RESTARTPOINT ) || \
					setofInfoPtr->infoStart[ 1 ].fieldType == FIELDTYPE_IDENTIFIER );
			attributeInfoPtr = setofInfoPtr->infoStart + 1;

⌨️ 快捷键说明

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