certext.c

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

C
1,330
字号
			if( !isprint( ch ) )
				isOK = FALSE;
			if( attributeInfoPtr->fieldType == BER_STRING_PRINTABLE && \
				( ( ch >= '!' && ch <= '&' ) || ch == '*' || ch == ';' || \
				  ch == '<' || ch == '>' || ch == '@' || \
				  ( ch >= '[' && ch <= '`' ) || ch >= '{' ) )
				isOK = FALSE;
			if( !isOK )
				{
				if( errorType != NULL )
					*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
				return( CRYPT_ARGERROR_STR1 );
				}
			}
		}

	return( CRYPT_OK );
	}

int addAttributeField( ATTRIBUTE_LIST **attributeListPtr,
					   const CRYPT_ATTRIBUTE_TYPE fieldID,
					   const CRYPT_ATTRIBUTE_TYPE subFieldID,
					   const void *data, const int dataLength,
					   const int flags, CRYPT_ATTRIBUTE_TYPE *errorLocus, 
					   CRYPT_ERRTYPE_TYPE *errorType )
	{
	const ATTRIBUTE_TYPE attributeType = ( fieldID >= CRYPT_FIRST_CMS ) ? \
									ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;
	CRYPT_ATTRIBUTE_TYPE attributeID;
	const ATTRIBUTE_INFO *attributeInfoPtr = fieldIDToAttribute( attributeType,
										fieldID, subFieldID, &attributeID );
	ATTRIBUTE_LIST *newElement, *insertPoint, *prevElement = NULL;
	int status;

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

	/* Check the field's validity if necessary */
	status = checkAttributeField( *attributeListPtr, attributeInfoPtr, 
								  fieldID, subFieldID, data, dataLength, 
								  flags, errorType );
	if( cryptStatusError( status ) )
		{
		if( errorType != NULL && cryptStatusError( *errorType ) )
			/* If we encountered an error which sets the error type, record
			   the locus */
			*errorLocus = fieldID;
		return( status );
		}

	/* Find the location at which to insert this attribute field (this 
	   assumes that the fieldIDs are defined in sorted order) */
	insertPoint = *attributeListPtr;
	while( insertPoint != NULL && \
		   insertPoint->fieldID != CRYPT_ATTRIBUTE_NONE && \
		   insertPoint->fieldID <= fieldID )
		{
		/* If it's a composite field which can have multiple fields with the 
		   same field ID (eg a GeneralName), exit if the overall field ID is 
		   greater (the component belongs to a different field entirely) or 
		   if the field ID is the same and the subfield ID is greater (if 
		   the component belongs to the same field) */
		if( subFieldID != CRYPT_ATTRIBUTE_NONE && \
			insertPoint->fieldID == fieldID && \
			insertPoint->subFieldID > subFieldID )
			break;

		prevElement = insertPoint;
		insertPoint = insertPoint->next;
		}
	insertPoint = prevElement;

	/* Allocate memory for the new element and copy the information across.
	   If it's a simple type we can assign it to the simple value in the
	   element itself, otherwise we either copy it into the storage in the
	   element or allocate seperate storage and copy it into that.  Something
	   which encodes to NULL isn't really a numeric type, but we class it as
	   such so that any attempt to read it returns CRYPT_UNUSED as the value */
	if( ( newElement  = ( ATTRIBUTE_LIST * ) malloc( sizeof( ATTRIBUTE_LIST ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( newElement, 0, sizeof( ATTRIBUTE_LIST ) );
	newElement->attributeID = attributeID;
	newElement->fieldID = fieldID;
	newElement->subFieldID = subFieldID;
	newElement->flags = flags;
	newElement->fieldType = attributeInfoPtr->fieldType;
	switch( attributeInfoPtr->fieldType )
		{
		case BER_INTEGER:
		case BER_ENUMERATED:
		case BER_BITSTRING:
		case BER_BOOLEAN:
		case BER_NULL:
		case FIELDTYPE_CHOICE:
			newElement->value = *( ( int * ) data );
			if( attributeInfoPtr->fieldType == BER_BOOLEAN )
				/* Force it to the correct type if it's a boolean */
				newElement->value = ( newElement->value ) ? TRUE : FALSE;
			if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
				/* For encoding purposes the subfield ID is set to the ID of 
				   the CHOICE selection */
				newElement->subFieldID = newElement->value;
			break;

		case BER_OBJECT_IDENTIFIER:
			/* If it's a BER/DER-encoded OID copy it in as is, otherwise 
			   convert it from the text form */
			if( ( ( BYTE * ) data )[ 0 ] == BER_OBJECT_IDENTIFIER )
				{
				memcpy( newElement->smallData, data, dataLength );
				newElement->dataLength = dataLength;
				}
			else
				newElement->dataLength = textToOID( data, dataLength,
													newElement->smallData );
			break;

		case 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 */
			if( *( ( int * ) data ) != CRYPT_UNUSED )
				newElement->data = ( void * ) data;
			break;

		case FIELDTYPE_IDENTIFIER:
			/* This is a placeholder entry with no explicit value */
			newElement->value = CRYPT_UNUSED;
			break;

		default:
			assert( dataLength > 0 );
			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( attributeListPtr, insertPoint, 
						newElement, newElement );

	return( CRYPT_OK );
	}

/* Copy an attribute from one attribute list to another.  This is an all-or-
   nothing copy in that it either copies a complete attribute or nothing at
   all */

static int copyAttributeField( ATTRIBUTE_LIST **destAttributeField,
							   const ATTRIBUTE_LIST *srcAttributeField )
	{
	ATTRIBUTE_LIST *newElement;
	int status = CRYPT_OK;

	assert( isWritePtr( destAttributeField, ATTRIBUTE_LIST * ) );
	assert( isReadPtr( srcAttributeField, ATTRIBUTE_LIST ) );

	/* Allocate memory for the new element and copy the information across.
	   If it's a simple type we can assign it to the simple value in the
	   element itself, otherwise we either copy into the storage in the
	   element or allocate seperate storage and copy it into that */
	*destAttributeField = NULL;
	if( ( newElement = ( ATTRIBUTE_LIST * ) malloc( sizeof( ATTRIBUTE_LIST ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memcpy( newElement, srcAttributeField, sizeof( ATTRIBUTE_LIST ) );
	if( srcAttributeField->dataLength > CRYPT_MAX_TEXTSIZE )
		{
		/* If the payload doesn't fit into the attribute structure, copy the
		   separate data payload across */
		if( ( newElement->data = malloc( srcAttributeField->dataLength ) ) == NULL )
			status = CRYPT_ERROR_MEMORY;
		else
			memcpy( newElement->data, srcAttributeField->data,
					srcAttributeField->dataLength );
		}
	else
		if( srcAttributeField->fieldType == FIELDTYPE_DN )
			/* If the field contains a DN, copy the DN across */
			status = copyDN( ( void ** ) &newElement->data,
							 srcAttributeField->data );
	if( cryptStatusError( status ) )
		{
		assert( newElement->data == NULL );
		free( newElement );
		return( status );
		}
	newElement->next = newElement->prev = NULL;
	*destAttributeField = newElement;

	return( CRYPT_OK );
	}

static int copyAttribute( ATTRIBUTE_LIST **destListHeadPtr,
						  const ATTRIBUTE_LIST *srcListPtr,
						  const BOOLEAN subjectToIssuer )
	{
	const CRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;
	CRYPT_ATTRIBUTE_TYPE newAttributeID = attributeID, newFieldID = attributeID;
	ATTRIBUTE_LIST *newAttributeListHead = NULL, *newAttributeListTail;
	ATTRIBUTE_LIST *insertPoint, *prevElement = NULL;

	assert( isWritePtr( destListHeadPtr, ATTRIBUTE_LIST * ) );
	assert( isReadPtr( srcListPtr, ATTRIBUTE_LIST ) );

	/* If we're copying from an issuer to a subject attribute list and the
	   field is an altName or keyIdentifier, change the field type from
	   issuer.subjectAltName to subject.issuerAltName or
	   issuer.subjectKeyIdentifier to subject.authorityKeyIdentifier */
	if( subjectToIssuer )
		{
		if( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )
			newAttributeID = newFieldID = CRYPT_CERTINFO_ISSUERALTNAME;
		if( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )
			{
			newAttributeID = CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;
			newFieldID = CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER;
			}
		}

	/* Find the location at which to insert this attribute.  For now we
	   assume that the fieldIDs are defined in sorted order, we may need to
	   change this and add internal mapping if new fieldIDs are added out of
	   order */
	for( insertPoint = *destListHeadPtr;
		 insertPoint != NULL && insertPoint->attributeID < newAttributeID && \
			insertPoint->fieldID != CRYPT_ATTRIBUTE_NONE;
		 insertPoint = insertPoint->next )
		prevElement = insertPoint;
	insertPoint = prevElement;

	/* Build a new attribute list containing the attribute fields */
	while( srcListPtr != NULL && srcListPtr->attributeID == attributeID )
		{
		ATTRIBUTE_LIST *newAttributeField;
		int status;

		/* Copy the field across, append it to the new attribute list, and
		   adjust the type for issuer->subject copying if necessary */
		status = copyAttributeField( &newAttributeField, srcListPtr );
		if( cryptStatusError( status ) )
			{
			deleteAttributes( &newAttributeListHead );
			return( CRYPT_ERROR_MEMORY );
			}
		if( newAttributeListHead == NULL )
			newAttributeListHead = newAttributeListTail = newAttributeField;
		else
			{
			newAttributeListTail->next = newAttributeField;
			newAttributeField->prev = newAttributeListTail;
			newAttributeListTail = newAttributeField;
			}
		if( newAttributeID != attributeID )
			{
			newAttributeField->attributeID = newAttributeID;
			newAttributeField->fieldID = newFieldID;
			}

		/* Move on to the next field */
		srcListPtr = srcListPtr->next;
		}

	/* Link the new list into the existing list at the appropriate position */
	insertListElements( destListHeadPtr, insertPoint, newAttributeListHead,
						newAttributeListTail );

	return( CRYPT_OK );
	}

/* Copy a complete attribute list */

int copyAttributes( ATTRIBUTE_LIST **destListHeadPtr,
					ATTRIBUTE_LIST *srcListPtr,
					CRYPT_ATTRIBUTE_TYPE *errorLocus, 
					CRYPT_ERRTYPE_TYPE *errorType )
	{
	ATTRIBUTE_LIST *attributeListCursor = srcListPtr;

	assert( isWritePtr( destListHeadPtr, ATTRIBUTE_LIST * ) );
	assert( isReadPtr( srcListPtr, ATTRIBUTE_LIST ) );

	/* Make a first pass down the list checking that the attribute to copy
	   isn't already present, first for recognised attributes and then for
	   unrecognised ones.  We have to do this separately since once we begin
	   the copy process it's rather hard to undo it.  Note that in theory 
	   there are some attributes which can have multiple instances of a field
	   present, which means we could allow them to appear in both the source
	   and destination lists, however if this occurs it's more likely to be 
	   an error than a desire to merge two disparate collections of 
	   attributes */
	while( attributeListCursor != NULL && \
		   !isBlobAttribute( attributeListCursor ) )
		{
		if( findAttributeField( *destListHeadPtr,
				attributeListCursor->fieldID, CRYPT_ATTRIBUTE_NONE ) != NULL )
			{
			*errorLocus = attributeListCursor->fieldID;
			*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
			return( CRYPT_ERROR_DUPLICATE );
			}
		attributeListCursor = attributeListCursor->next;
		}
	while( attributeListCursor != NULL )
		{
		if( findAttributeByOID( *destListHeadPtr, attributeListCursor->oid ) != NULL )
			{
			/* We can't set the locus for blob-type attributes since it's not
			   a known attribute */
			*errorLocus = CRYPT_ATTRIBUTE_NONE;
			*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
			return( CRYPT_ERROR_DUPLICATE );
			}
		attributeListCursor = attributeListCursor->next;
		}

	/* Make a second pass copying everything across */
	while( srcListPtr != NULL && !isBlobAttribute( srcListPtr ) )
		{
		CRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;
		int status;

⌨️ 快捷键说明

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