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

📄 certext.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:

	switch( attributeInfoPtr->fieldType )
		{
		case FIELDTYPE_BLOB:
			/* It's a blob field, make sure that it's a valid ASN.1 object */
			if( cryptStatusError( getObjectLength( data, dataLength ) ) )
				{
				if( errorType != NULL )
					*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
				return( CRYPT_ARGERROR_STR1 );
				}
			return( CRYPT_OK );

		case BER_STRING_NUMERIC:
			{
			const char *dataPtr = data;
			int i;

			/* Make sure it's a numeric string */
			for( i = 0; i < dataLength; i++ )
				if( !isDigit( dataPtr[ i ] ) )
					{
					if( errorType != NULL )
						*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
					return( CRYPT_ARGERROR_STR1 );
					}
			return( CRYPT_OK );
			}

		case BER_STRING_IA5:
		case BER_STRING_ISO646:
		case BER_STRING_PRINTABLE:
			/* Make sure it's an ASCII string of the correct type */
			if( !checkTextStringData( data, dataLength, 
					( attributeInfoPtr->fieldType == BER_STRING_PRINTABLE ) ? \
					TRUE : FALSE ) )
				{
				if( errorType != NULL )
					*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
				return( CRYPT_ARGERROR_STR1 );
				}
			return( CRYPT_OK );
		}

	return( CRYPT_OK );
	}

/* Add an attribute field to a list of attributes at the appropriate 
   location */

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_CERTINFO_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;
	BOOLEAN isNumeric = FALSE;
	int storageSize, 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 */
	status = checkAttributeField( *attributeListPtr, attributeInfoPtr, 
								  fieldID, subFieldID, data, dataLength, 
								  flags, errorType );
	if( cryptStatusError( status ) )
		{
		if( status == OK_SPECIAL )
			/* Special indicator to tell us that the value is non-string
			   numeric data */
			isNumeric = TRUE;
		else
			{
			if( errorType != NULL && cryptStatusError( *errorType ) )
				/* If we encountered an error that sets the error type, 
				   record the locus */
				*errorLocus = fieldID;
			return( status );
			}
		}
	assert( isNumeric || \
			( ( attributeInfoPtr->fieldType == FIELDTYPE_DN || \
				attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER ) && \
			  dataLength == CRYPT_UNUSED ) || \
			dataLength > 0 );

	/* 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 that can have multiple fields with the 
		   same field ID (e.g.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
	   that 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 */
	storageSize = ( isNumeric || \
					attributeInfoPtr->fieldType == FIELDTYPE_DN || \
					attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER ) ? \
				  0 : dataLength; 
	if( ( newElement = ( ATTRIBUTE_LIST * ) \
					   clAlloc( "addAttributeField", sizeof( ATTRIBUTE_LIST ) + \
													 storageSize ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	initVarStruct( newElement, ATTRIBUTE_LIST, storageSize );
	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->intValue = *( ( int * ) data );
			if( attributeInfoPtr->fieldType == BER_BOOLEAN )
				/* Force it to the correct type if it's a boolean */
				newElement->intValue = ( newElement->intValue ) ? 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->intValue;
			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->value, data, dataLength );
				newElement->valueLength = dataLength;
				}
			else
				newElement->valueLength = textToOID( data, dataLength,
													 newElement->value );
			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 */
			newElement->value = ( *( ( int * ) data ) == CRYPT_UNUSED ) ? \
								NULL : ( void * ) data;
			break;

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

		default:
			assert( dataLength > 0 );
			memcpy( newElement->value, data, dataLength );
			newElement->valueLength = dataLength;
			break;
		}
	insertDoubleListElement( attributeListPtr, insertPoint, 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 */
	*destAttributeField = NULL;
	if( ( newElement = ( ATTRIBUTE_LIST * ) \
					   clAlloc( "copyAttributeField", \
								sizeofVarStruct( srcAttributeField, \
												 ATTRIBUTE_LIST ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	copyVarStruct( newElement, srcAttributeField, ATTRIBUTE_LIST );
	if( srcAttributeField->fieldType == FIELDTYPE_DN )
		{
		/* If the field contains a DN, copy the DN across */
		status = copyDN( ( void ** ) &newElement->value,
						 srcAttributeField->value );
		if( cryptStatusError( status ) )
			{
			endVarStruct( newElement, ATTRIBUTE_LIST );
			clFree( "copyAttributeField", 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 */
	insertDoubleListElements( 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 that 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 )
		{
		assert( isBlobAttribute( attributeListCursor ) );
		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;

⌨️ 快捷键说明

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