certext.c

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,330 行 · 第 1/4 页

C
1,330
字号

		if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_PREVIOUS )
			while( count-- && newCursor->prev != NULL && \
				   newCursor->prev->attributeID == attributeID && \
				   newCursor->prev->fieldID == fieldID && \
				   newCursor->prev->subFieldID == subFieldID )
				newCursor = newCursor->prev;
		else
			while( count-- && newCursor->next != NULL && \
				   newCursor->next->attributeID == attributeID && \
				   newCursor->next->fieldID == fieldID && \
				   newCursor->next->subFieldID == subFieldID )
				newCursor = newCursor->next;

		if( !absMove && *currentCursor == newCursor )
			return( CRYPT_ERROR_NOTFOUND );
		*currentCursor = ( ATTRIBUTE_LIST * ) newCursor;
		return( CRYPT_OK );
		}

	/* Moving by attribute is a bit more complex.  First we find the start or
	   end of the current attribute, if there's another attribute before or
	   after it move back/forwards into that attribute and find the start of
	   that.  This has the effect of moving us from anywhere in the current
	   attribute to the start of the preceding or following attribute.
	   Finally, we repeat this as required */
	if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_PREVIOUS )
		while( count-- && newCursor != NULL )
			{
			lastCursor = newCursor;
			newCursor = findAttributeStart( findAttributeStart( newCursor )->prev );
			}
	else
		while( count-- && newCursor != NULL && \
			   newCursor->attributeID != CRYPT_ATTRIBUTE_NONE )
			{
			lastCursor = newCursor;
			newCursor = findAttributeEnd( newCursor )->next;
			}

	/* We've gone as far as we can.  If the new cursor is NULL, we've reached
	   the start or end of the attribute list, in case we haven't moved at all
	   we call findAttributeStart() to move to the first field.  If the new
	   cursor isn't NULL, it's located on the next or previous attribute */
	if( newCursor == NULL )
		*currentCursor = findAttributeStart( lastCursor );
	else
		*currentCursor = ( ATTRIBUTE_LIST * ) newCursor;
	if( *currentCursor == NULL )
		/* Positioning in null attribute lists is always unsuccessful */
		return( CRYPT_ERROR_NOTFOUND );
	if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_LAST )
		/* Absolute positioning is always successful */
		return( CRYPT_OK );
	return( ( ( *currentCursor )->attributeID == attributeID ) ? \
			CRYPT_ERROR_NOTFOUND : CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Attribute Management Routines					*
*																			*
****************************************************************************/

/* Insert elements into an attribute list after the given insertion point */

static void insertListElements( ATTRIBUTE_LIST **listHeadPtr,
								ATTRIBUTE_LIST *insertPoint,
								ATTRIBUTE_LIST *newStartElement,
								ATTRIBUTE_LIST *newEndElement )
	{
	assert( isWritePtr( listHeadPtr, ATTRIBUTE_LIST * ) );

	/* If it's an empty list, make this the new list */
	if( *listHeadPtr == NULL )
		{
		*listHeadPtr = newStartElement;
		return;
		}

	assert( isWritePtr( *listHeadPtr, ATTRIBUTE_LIST ) );
	assert( isWritePtr( newStartElement, ATTRIBUTE_LIST ) );
	assert( isWritePtr( newEndElement, ATTRIBUTE_LIST ) );

	/* If we're inserting at the start of the list, make this the new first
	   element */
	if( insertPoint == NULL )
		{
		/* Insert the element at the start of the list */
		newEndElement->next = *listHeadPtr;
		( *listHeadPtr )->prev = newEndElement;
		*listHeadPtr = newStartElement;
		return;
		}

	assert( isWritePtr( insertPoint, ATTRIBUTE_LIST ) );

	/* Insert the element in the middle or end of the list.  Update the links
	   for the next element */
	newEndElement->next = insertPoint->next;
	if( insertPoint->next != NULL )
		insertPoint->next->prev = newEndElement;

	/* Update the links for the previous element */
	insertPoint->next = newStartElement;
	newStartElement->prev = insertPoint;
	}

/* Add a blob-type attribute to a list of attributes */

int addAttribute( const ATTRIBUTE_TYPE attributeType,
				  ATTRIBUTE_LIST **listHeadPtr, const BYTE *oid,
				  const BOOLEAN criticalFlag, const void *data,
				  const int dataLength )
	{
	ATTRIBUTE_LIST *newElement, *insertPoint;

	assert( isWritePtr( listHeadPtr, ATTRIBUTE_LIST * ) );
	assert( isReadPtr( oid, 3 ) );
	assert( criticalFlag == TRUE || criticalFlag == FALSE );
	assert( !checkBadPtrRead( data, dataLength ) );
	assert( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE );

	/* If this attribute type is already handled as a non-blob attribute,
	   don't allow it to be added as a blob as well.  This avoids problems
	   with the same attribute being added twice, once as a blob and once as
	   a non-blob.  In addition it forces the caller to use the (recommended)
	   normal attribute handling mechanism which allows for proper type
	   checking */
	if( oidToAttribute( attributeType, oid ) != NULL )
		return( CRYPT_ERROR_PERMISSION );

	/* Find the correct place in the list to insert the new element */
	if( *listHeadPtr != NULL )
		{
		ATTRIBUTE_LIST *prevElement = NULL;

		for( insertPoint = *listHeadPtr; insertPoint != NULL;
			 insertPoint = insertPoint->next )
			{
			/* Make sure this blob attribute isn't already present */
			if( insertPoint->attributeID != CRYPT_ATTRIBUTE_NONE && \
				sizeofOID( insertPoint->oid ) == sizeofOID( oid ) && \
				!memcmp( insertPoint->oid, oid, sizeofOID( oid ) ) )
				return( CRYPT_ERROR_INITED );

			prevElement = insertPoint;
			}
		insertPoint = prevElement;
		}

	/* Allocate memory for the new element and copy the information across */
	if( ( newElement  = ( ATTRIBUTE_LIST * ) malloc( sizeof( ATTRIBUTE_LIST ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( newElement, 0, sizeof( ATTRIBUTE_LIST ) );
	memcpy( newElement->oid, oid, sizeofOID( oid ) );
	newElement->flags = criticalFlag ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE;
	if( dataLength <= CRYPT_MAX_TEXTSIZE )
		memcpy( newElement->smallData, data, dataLength );
	else
		{
		if( ( newElement->data = malloc( dataLength ) ) == NULL )
			{
			free( newElement );
			return( CRYPT_ERROR_MEMORY );
			}
		memcpy( newElement->data, data, dataLength );
		}
	newElement->dataLength = dataLength;
	insertListElements( listHeadPtr, insertPoint, newElement, newElement );

	return( CRYPT_OK );
	}

/* Add an attribute field at the appropriate location to a list of
   attributes after checking its validity */

static int checkAttributeField( const ATTRIBUTE_LIST *attributeListPtr,
								const ATTRIBUTE_INFO *attributeInfoPtr,
								const CRYPT_ATTRIBUTE_TYPE fieldID,
								const CRYPT_ATTRIBUTE_TYPE subFieldID,
								const void *data, const int dataLength,
								const int flags, 
								CRYPT_ERRTYPE_TYPE *errorType )
	{
	const ATTRIBUTE_TYPE attributeType = ( fieldID >= CRYPT_FIRST_CMS ) ? \
									ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;
	ATTRIBUTE_LIST *attributeListSearchPtr;

	assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );
	assert( dataLength == CRYPT_UNUSED || \
			( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE ) );
	assert( dataLength == CRYPT_UNUSED || \
			!checkBadPtrRead( data, dataLength ) );
	assert( !( flags & ATTR_FLAG_INVALID ) );

	/* Make sure that a valid field has been specified, and that this field
	   isn't already present as a non-default entry unless it's a field for
	   which multiple values are allowed */
	if( attributeInfoPtr == NULL )
		return( CRYPT_ARGERROR_VALUE );
	attributeListSearchPtr = findAttributeField( attributeListPtr, fieldID,
												 subFieldID );
	if( attributeListSearchPtr != NULL && \
		!( ( attributeInfoPtr->flags & FL_MULTIVALUED ) || \
		   ( flags & ATTR_FLAG_MULTIVALUED ) ) )
		{
		if( errorType != NULL )
			*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
		return( CRYPT_ERROR_INITED );
		}

	/* If it's a blob field, don't do any type checking.  This is a special
	   case which differs from FIELDTYPE_BLOB in that it corresponds to an
	   ASN.1 value which is mis-encoded by one or more implementations so we
	   have to accept absolutely anything at this point */
	if( flags & ATTR_FLAG_BLOB )
		return( CRYPT_OK );

	/* If it's an identifier or special-case field, make sure all parameters
	   are correct */
	if( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )
		{
		assert( dataLength == CRYPT_UNUSED );
		if( *( ( int * ) data ) != CRYPT_UNUSED )
			return( CRYPT_ARGERROR_NUM1 );

		return( CRYPT_OK );
		}
	if( attributeInfoPtr->fieldType == FIELDTYPE_DN )
		{
		/* When creating a new cert, this is a placeholder to indicate that 
		   a DN structure is being instantiated.  When reading an encoded 
		   cert, this is the decoded DN structure */
		assert( dataLength == CRYPT_UNUSED );
		return( CRYPT_OK );
		}

	/* If it's an OID, convert it to a binary OID (which performs a syntax
	   check on the OID) */
	if( attributeInfoPtr->fieldType == BER_OBJECT_IDENTIFIER )
		{
		const BYTE *oidPtr = data;
		BYTE binaryOID[ MAX_OID_SIZE ];

		/* If it's a BER/DER-encoded OID, make sure it's valid ASN.1 */
		if( oidPtr[ 0 ] == BER_OBJECT_IDENTIFIER )
			{
			if( oidPtr[ 1 ] == dataLength - 2 )
				return( CRYPT_OK );
			}
		else
			/* It's a text OID, check the syntax and make sure the length
			   is valid */
			if( textToOID( data, dataLength, binaryOID ) )
				return( CRYPT_OK );

		if( errorType != NULL )
			*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
		return( CRYPT_ARGERROR_STR1 );
		}

	/* If it's an integer type, type check it */
	if( attributeInfoPtr->fieldType == BER_INTEGER || \
		attributeInfoPtr->fieldType == BER_ENUMERATED || \
		attributeInfoPtr->fieldType == BER_BITSTRING || \
		attributeInfoPtr->fieldType == BER_BOOLEAN || \
		attributeInfoPtr->fieldType == BER_NULL || \
		attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
		{
		int value = *( ( int * ) data );

		assert( dataLength == CRYPT_UNUSED );

		/* BOOLEAN data is accepted as zero/nonzero so it's always valid */
		if( attributeInfoPtr->fieldType == BER_BOOLEAN )
			return( CRYPT_OK );

		/* Check that the data size and range is valid */
		if( value < attributeInfoPtr->lowRange || \
			value > attributeInfoPtr->highRange )
			{
			if( errorType != NULL )
				*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
			return( CRYPT_ARGERROR_NUM1 );
			}

		return( CRYPT_OK );
		}

	/* Type check the value */
	if( dataLength < attributeInfoPtr->lowRange || \
		dataLength > attributeInfoPtr->highRange )
		{
		if( errorType != NULL )
			*errorType = CRYPT_ERRTYPE_ATTR_SIZE;
		return( CRYPT_ARGERROR_NUM1 );
		}
	if( attributeInfoPtr->fieldType == FIELDTYPE_BLOB )
		{
		/* If it's a blob field, make sure it's a valid ASN.1 object */
		if( cryptStatusError( getObjectLength( data, dataLength ) ) )
			{
			if( errorType != NULL )
				*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
			return( CRYPT_ARGERROR_STR1 );
			}
		}
	if( attributeInfoPtr->fieldType == BER_STRING_NUMERIC )
		{
		const char *dataPtr = data;
		int i;

		for( i = 0; i < dataLength; i++ )
			if( !isdigit( dataPtr[ i ] ) )
				{
				if( errorType != NULL )
					*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
				return( CRYPT_ARGERROR_STR1 );
				}
		}
	if( attributeInfoPtr->fieldType == BER_STRING_IA5 || \
		attributeInfoPtr->fieldType == BER_STRING_ISO646 || \
		attributeInfoPtr->fieldType == BER_STRING_PRINTABLE )
		{
		const char *dataPtr = data;
		BOOLEAN isOK = TRUE;
		int i;

		for( i = 0; i < dataLength; i++ )
			{
			const char ch = dataPtr[ i ];

⌨️ 快捷键说明

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