certext.c

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

C
1,330
字号
/****************************************************************************
*																			*
*					Certificate Attribute Management Routines				*
*						Copyright Peter Gutmann 1996-2002					*
*																			*
****************************************************************************/

#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL ) ||  defined( INC_CHILD )
  #include "asn1.h"
  #include "cert.h"
  #include "certattr.h"
#else
  #include "keymgmt/asn1.h"
  #include "keymgmt/cert.h"
  #include "keymgmt/certattr.h"
#endif /* Compiler-specific includes */

/* Prototypes for functions in cryptcrt.c */

int textToOID( const char *oid, const int oidLength, BYTE *binaryOID );

/****************************************************************************
*																			*
*								Attribute Type Mapping						*
*																			*
****************************************************************************/

/* Get the attribute information for a given OID */

const ATTRIBUTE_INFO *oidToAttribute( const ATTRIBUTE_TYPE attributeType,
									  const BYTE *oid )
	{
	const ATTRIBUTE_INFO *attributeInfoPtr = \
							selectAttributeInfo( attributeType );
	const int length = sizeofOID( oid );

	while( attributeInfoPtr->fieldID != CRYPT_ERROR )
		{
		if( attributeInfoPtr->oid != NULL && \
			sizeofOID( attributeInfoPtr->oid ) == length && \
			!memcmp( attributeInfoPtr->oid, oid, length ) )
			return( attributeInfoPtr );
		attributeInfoPtr++;
		}

	/* It's an unknown attribute */
	return( NULL );
	}

/* Get the attribute and attributeID for a field ID */

static const ATTRIBUTE_INFO *fieldIDToAttribute( const ATTRIBUTE_TYPE attributeType,
		const CRYPT_ATTRIBUTE_TYPE fieldID, const CRYPT_ATTRIBUTE_TYPE subFieldID,
		CRYPT_ATTRIBUTE_TYPE *attributeID )
	{
	const ATTRIBUTE_INFO *attributeInfoPtr = \
							selectAttributeInfo( attributeType );
	int i;

	/* Clear the return value */
	if( attributeID != NULL )
		*attributeID = CRYPT_ERROR;

	/* Find the information on this attribute field */
	for( i = 0; attributeInfoPtr[ i ].fieldID != CRYPT_ERROR; i++ )
		{
		/* If the previous entry doesn't have more data following it, the
		   current entry is the start of a complete attribute and therefore
		   contains the attribute ID */
		if( attributeID != NULL && \
			( !i || !( attributeInfoPtr[ i - 1 ].flags & FL_MORE ) ) )
			{
			int j;

			/* Usually the attribute ID is the fieldID for the first entry,
			   however in some cases the attributeID is the same as the
			   fieldID and isn't specified until later on (denoted by the
			   fieldID being FIELDID_FOLLOWS), so we have to look ahead to
			   find it */
			*attributeID = attributeInfoPtr[ i ].fieldID;
			for( j = i + 1; *attributeID == FIELDID_FOLLOWS; j++ )
				*attributeID = attributeInfoPtr[ j ].fieldID;
			}

		/* Check whether the field ID for this entry matches the one we want */
		if( attributeInfoPtr[ i ].fieldID == fieldID )
			{
			ATTRIBUTE_INFO *altEncodingTable = \
						( ATTRIBUTE_INFO * ) attributeInfoPtr[ i ].extraData;

			/* If we're after a subfield match as well, try and match the
			   subfield */
			if( subFieldID != CRYPT_ATTRIBUTE_NONE && altEncodingTable != NULL )
				{
				for( i = 0; altEncodingTable[ i ].fieldID != CRYPT_ERROR; i++ )
					if( altEncodingTable[ i ].fieldID == subFieldID )
						return( &altEncodingTable[ i ] );

				return( NULL );
				}

			return( &attributeInfoPtr[ i ] );
			}
		}

	return( NULL );
	}

/****************************************************************************
*																			*
*					Attribute Location/Cursor Movement Routines				*
*																			*
****************************************************************************/

/* Find the start and end of an attribute from a field within the
   attribute */

static ATTRIBUTE_LIST *findAttributeStart( const ATTRIBUTE_LIST *attributeListPtr )
	{
	CRYPT_ATTRIBUTE_TYPE attributeID;

	if( attributeListPtr == NULL )
		return( NULL );
	attributeID = attributeListPtr->attributeID;

	/* Move backwards until we find the start of the attribute */
	while( attributeListPtr->prev != NULL && \
		   attributeListPtr->prev->attributeID == attributeID )
		attributeListPtr = attributeListPtr->prev;

	return( ( ATTRIBUTE_LIST * ) attributeListPtr );
	}

static ATTRIBUTE_LIST *findAttributeEnd( const ATTRIBUTE_LIST *attributeListPtr )
	{
	CRYPT_ATTRIBUTE_TYPE attributeID;

	if( attributeListPtr == NULL )
		return( NULL );
	attributeID = attributeListPtr->attributeID;

	/* Move forwards until we find the start of the next attribute */
	while( attributeListPtr->next != NULL && \
		   attributeListPtr->next->attributeID == attributeID )
		attributeListPtr = attributeListPtr->next;

	return( ( ATTRIBUTE_LIST * ) attributeListPtr );
	}

/* Find an attribute in a list of certificate attributes by object identifier
   (for blob-type attributes) or by field and subfield ID (for known
   attributes), with extended handling for fields with default values */

ATTRIBUTE_LIST *findAttributeByOID( const ATTRIBUTE_LIST *attributeListPtr,
									const BYTE *oid )
	{
	/* Find the position of this component in the list */
	while( attributeListPtr != NULL && \
		   ( sizeofOID( attributeListPtr->oid ) != sizeofOID( oid ) || \
			 memcmp( attributeListPtr->oid, oid, sizeofOID( oid ) ) ) )
		 attributeListPtr = attributeListPtr->next;

	return( ( ATTRIBUTE_LIST * ) attributeListPtr );
	}

ATTRIBUTE_LIST *findAttributeField( const ATTRIBUTE_LIST *attributeListPtr,
									const CRYPT_ATTRIBUTE_TYPE fieldID,
									const CRYPT_ATTRIBUTE_TYPE subFieldID )
	{
	/* Find the position of this component in the list */
	while( attributeListPtr != NULL && \
		   attributeListPtr->fieldID != fieldID )
		attributeListPtr = attributeListPtr->next;
	if( subFieldID == CRYPT_ATTRIBUTE_NONE )
		return( ( ATTRIBUTE_LIST * ) attributeListPtr );

	/* Find the subfield in the field */
	while( attributeListPtr != NULL && \
		   attributeListPtr->fieldID == fieldID )
		{
		if( attributeListPtr->subFieldID == subFieldID )
			return( ( ATTRIBUTE_LIST * ) attributeListPtr );
		attributeListPtr = attributeListPtr->next;
		}

	return( NULL );
	}

ATTRIBUTE_LIST *findAttributeFieldEx( const ATTRIBUTE_LIST *attributeListPtr,
									  const CRYPT_ATTRIBUTE_TYPE fieldID )
	{
	static const ATTRIBUTE_LIST defaultField = DEFAULTFIELD_VALUE;
	static const ATTRIBUTE_LIST completeAttribute = COMPLETEATTRIBUTE_VALUE;
	const ATTRIBUTE_LIST *attributeListCursor = attributeListPtr;
	const ATTRIBUTE_INFO *attributeInfoPtr;
	const ATTRIBUTE_TYPE attributeType = ( fieldID >= CRYPT_FIRST_CMS ) ? \
									ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;
	CRYPT_ATTRIBUTE_TYPE attributeID;

	/* Find the position of this component in the list */
	while( attributeListCursor != NULL && \
		   attributeListCursor->fieldID != fieldID )
		attributeListCursor = attributeListCursor->next;
	if( attributeListCursor != NULL )
		return( ( ATTRIBUTE_LIST * ) attributeListCursor );

	/* The field isn't present in the list of attributes, check whether
	   the attribute itself is present and whether this field has a default
	   value */
	attributeInfoPtr = fieldIDToAttribute( attributeType, fieldID, 
										   CRYPT_ATTRIBUTE_NONE, &attributeID );
	if( attributeInfoPtr == NULL )
		/* There's no attribute containing this field, exit */
		return( NULL );

	/* Check whether any part of the attribute which contains the given 
	   field is present in the list of attribute fields */
	for( attributeListCursor = ( ATTRIBUTE_LIST * ) attributeListPtr;
		 attributeListCursor != NULL && \
			attributeListCursor->attributeID != attributeID;
		 attributeListCursor = attributeListCursor->next );
	if( attributeListCursor == NULL )
		return( NULL );

	/* Some other part of the attribute containing the given field is present 
	   in the list.  If this field wasn't found that could either be a 
	   default value (in which case we return an entry which denotes that 
	   this field is absent but has a default setting) or a field which 
	   denotes an entire constructed attribute (in which case we return an 
	   entry which denotes this) */
	if( attributeInfoPtr->flags & FL_DEFAULT )
		return( ( ATTRIBUTE_LIST * ) &defaultField );
	if( attributeInfoPtr->fieldType == BER_SEQUENCE )
		return( ( ATTRIBUTE_LIST * ) &completeAttribute );

	return( NULL );
	}

ATTRIBUTE_LIST *findAttribute( const ATTRIBUTE_LIST *attributeListPtr,
							   const CRYPT_ATTRIBUTE_TYPE fieldID )
	{
	const ATTRIBUTE_LIST *attributeListCursor = attributeListPtr;

	/* Finding an overall attribute is a bit more complex than finding a
	   field since we may be given an attribute ID (which denotes the entire
	   attribute) or a field ID (which denotes one field in the attribute).
	   First we check for a match on the attribute ID */
	while( attributeListCursor != NULL && \
		   attributeListCursor->attributeID != fieldID )
		attributeListCursor = attributeListCursor->next;
	if( attributeListCursor != NULL )
		return( ( ATTRIBUTE_LIST * ) attributeListCursor );

	/* It wasn't a (present) attribute ID, find the start of the attribute 
	   which contains this field */
	return( findAttributeStart( \
					findAttributeField( attributeListPtr, fieldID,
										CRYPT_ATTRIBUTE_NONE ) ) );
	}

/* Get the default value for an optional field of an attribute */

int getDefaultFieldValue( const CRYPT_ATTRIBUTE_TYPE fieldID )
	{
	const ATTRIBUTE_INFO *attributeInfoPtr = \
			fieldIDToAttribute( ( fieldID >= CRYPT_FIRST_CMS ) ? \
									ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE,
								fieldID, CRYPT_ATTRIBUTE_NONE, NULL );

	assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );

	return( ( int ) attributeInfoPtr->defaultValue );
	}

/* Move the attribute cursor relative to the current cursor position.  This
   moves as far as possible in the direction given and then returns an
   appropriate return code, either CRYPT_OK or CRYPT_ERROR_NOTFOUND if no
   movement is possible.  Note that it's possible to both return
   CRYPT_ERROR_NOTFOUND and update the cursor, for example if we're halfway
   through the first attribute then a position code of CRYPT_CURSOR_FIRST
   will move to the start of the attribute, but the error will be returned to
   indicate that it wasn't possible to move back before the current
   attribute */

int moveAttributeCursor( ATTRIBUTE_LIST **currentCursor,
						 const CRYPT_ATTRIBUTE_TYPE certInfoType, 
						 const int position )
	{
	const CRYPT_ATTRIBUTE_TYPE attributeID = ( *currentCursor )->attributeID;
	const ATTRIBUTE_LIST *newCursor = *currentCursor, *lastCursor = NULL;
	const BOOLEAN absMove = ( position == CRYPT_CURSOR_FIRST || \
							  position == CRYPT_CURSOR_LAST ) ? TRUE : FALSE;
	int count;

	assert( certInfoType == CRYPT_CERTINFO_CURRENT_EXTENSION || \
			certInfoType == CRYPT_CERTINFO_CURRENT_FIELD || \
			certInfoType == CRYPT_CERTINFO_CURRENT_COMPONENT );
	assert( position <= CRYPT_CURSOR_FIRST && \
			position >= CRYPT_CURSOR_LAST );

	/* Set the amount we want to move by based on the position code.  This
	   means we can handle the movement in a simple while loop instead of
	   having to special-case it for moves by one item */
	count = absMove ? INT_MAX : 1;

	/* Moving by field or component is relatively simple.  For fields we move
	   backwards or forwards until we either run out of fields or the next 
	   field belongs to a different attribute.  For components we move 
	   similarly, except that we stop when we reach a field whose attribute
	   type, field type, and subfield type don't match the current one */
	if( certInfoType == CRYPT_CERTINFO_CURRENT_FIELD )
		{
		if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_PREVIOUS )
			while( count-- && newCursor->prev != NULL && \
				   newCursor->prev->attributeID == attributeID )
				newCursor = newCursor->prev;
		else
			while( count-- && newCursor->next != NULL && \
				   newCursor->next->attributeID == attributeID )
				newCursor = newCursor->next;

		if( !absMove && *currentCursor == newCursor )
			return( CRYPT_ERROR_NOTFOUND );
		*currentCursor = ( ATTRIBUTE_LIST * ) newCursor;
		return( CRYPT_OK );
		}
	if( certInfoType == CRYPT_CERTINFO_CURRENT_COMPONENT )
		{
		const CRYPT_ATTRIBUTE_TYPE fieldID = ( *currentCursor )->fieldID;
		const CRYPT_ATTRIBUTE_TYPE subFieldID = ( *currentCursor )->subFieldID;

⌨️ 快捷键说明

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