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

📄 ext_wr.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
				return( swrite( stream, attributeInfoPtr->oid, size ) );

			case BER_INTEGER:
				return( writeShortInteger( stream, attributeInfoPtr->defaultValue, 
										   tag ) );

			case BER_SEQUENCE:
			case BER_SET:
				if( tag != DEFAULT_TAG )
					return( writeConstructed( stream, payloadSize, tag ) );
				return( ( fieldType == BER_SET ) ? \
						writeSet( stream, payloadSize ) : \
						writeSequence( stream, payloadSize ) );
			}
		
		retIntError();
		}

	/* It's a standard object, take the data from the user-supplied data */
	switch( fieldType )
		{
		case FIELDTYPE_BLOB:
			if( tag != DEFAULT_TAG )
				{
				/* This gets a bit messy because the blob is stored in 
				   encoded form in the attribute, to write it as a tagged 
				   value we have to write a different first byte */
				sputc( stream, getFieldEncodedTag( attributeInfoPtr ) );
				return( swrite( stream, ( ( BYTE * ) dataPtr ) + 1,
								attributeListPtr->valueLength - 1 ) );
				}
			return( swrite( stream, dataPtr, attributeListPtr->valueLength ) );

		case FIELDTYPE_DN:
			return( writeDN( stream, attributeListPtr->value, tag ) );

		case FIELDTYPE_IDENTIFIER:
			ENSURES( tag == DEFAULT_TAG );
			return( swrite( stream, attributeInfoPtr->oid, size ) );

		case FIELDTYPE_DISPLAYSTRING:
			if( tag == DEFAULT_TAG )
				{
				tag = ( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL ) ? \
					  BER_STRING_UTF8 : BER_STRING_ISO646;
				}
			return( writeCharacterString( stream, dataPtr, 
										  attributeListPtr->valueLength, 
										  tag ) );

		case BER_BITSTRING:
			return( writeBitString( stream, ( int ) \
									attributeListPtr->intValue, tag ) );

		case BER_BOOLEAN:
			return( writeBoolean( stream, ( BOOLEAN ) \
								  attributeListPtr->intValue, tag ) );

		case BER_ENUMERATED:
			return( writeEnumerated( stream, ( int ) \
									 attributeListPtr->intValue, tag ) );

		case BER_INTEGER:
			return( writeShortInteger( stream, attributeListPtr->intValue, 
									   tag ) );

		case BER_NULL:
			return( writeNull( stream, tag ) );

		case BER_OBJECT_IDENTIFIER:
			if( tag != DEFAULT_TAG )
				{
				/* This gets a bit messy because the OID is stored in 
				   encoded form in the attribute, to write it as a tagged 
				   value we have to write a different first byte */
				sputc( stream, getFieldEncodedTag( attributeInfoPtr ) );
				return( swrite( stream, ( ( BYTE * ) dataPtr ) + 1,
								attributeListPtr->valueLength - 1 ) );
				}
			return( swrite( stream, dataPtr, 
							attributeListPtr->valueLength ) );

		case BER_OCTETSTRING:
			/* If it's an integer equivalent to an OCTET STRING hole we need 
			   to use the INTEGER encoding rules rather than the OCTET 
			   STRING ones */
			if( attributeInfoPtr->flags & FL_ALIAS )
				{
				ENSURES( attributeInfoPtr->fieldEncodedType == BER_INTEGER );

				return( writeInteger( stream, dataPtr, 
									  attributeListPtr->valueLength, 
									  DEFAULT_TAG ) );
				}
			return( writeOctetString( stream, dataPtr, 
									  attributeListPtr->valueLength, 
									  tag ) );

		case BER_STRING_BMP:
		case BER_STRING_IA5:
		case BER_STRING_ISO646:
		case BER_STRING_NUMERIC:
		case BER_STRING_PRINTABLE:
		case BER_STRING_UTF8:
			return( writeCharacterString( stream, dataPtr, 
										  attributeListPtr->valueLength,
										  ( tag == DEFAULT_TAG ) ? \
											fieldType : \
											MAKE_CTAG_PRIMITIVE( tag ) ) );

		case BER_TIME_GENERALIZED:
			return( writeGeneralizedTime( stream, *( time_t * ) dataPtr, 
										  tag ) );

		case BER_TIME_UTC:
			return( writeUTCTime( stream, *( time_t * ) dataPtr, tag ) );
		}

	retIntError();
	}

/* Write an attribute */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeAttribute( INOUT STREAM *stream, 
						   INOUT ATTRIBUTE_LIST **attributeListPtrPtr,
						   const BOOLEAN wrapperTagSet, 
						   IN_RANGE( 0, 4 ) const int complianceLevel )
	{
	ATTRIBUTE_LIST *attributeListPtr = *attributeListPtrPtr;
	int flagSize, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
	assert( isReadPtr( *attributeListPtrPtr, sizeof( ATTRIBUTE_LIST ) ) );

	REQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \
			  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );

	/* If it's a non-blob attribute, write it field by field */
	if( !isBlobAttribute( attributeListPtr ) )
		{
		const BOOLEAN isConstructed = ( attributeListPtr->fifoEnd ) ? \
									  TRUE : FALSE;
		const ATTRIBUTE_INFO *attributeInfoPtr = ( isConstructed ) ? \
			attributeListPtr->encodingFifo[ attributeListPtr->fifoEnd - 1 ] : \
			attributeListPtr->attributeInfoPtr;
		const CRYPT_ATTRIBUTE_TYPE attributeID = attributeListPtr->attributeID;
		int dataLength, length = sizeofOID( attributeInfoPtr->oid );
		int iterationCount;

		assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );

		/* Determine the size of the attribute payload */
		flagSize = ( ( attributeInfoPtr->flags & FL_CRITICAL ) || \
					 ( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) ) ? \
				   sizeofBoolean() : 0;
		if( isConstructed && attributeInfoPtr->fieldType != FIELDTYPE_CHOICE )
			{
			dataLength = ( int ) sizeofObject( \
				attributeListPtr->sizeFifo[ attributeListPtr->fifoEnd - 1 ] );
			}
		else
			dataLength = attributeListPtr->encodedSize;

		/* Write the outer SEQUENCE, OID, critical flag (if it's set) and
		   appropriate wrapper for the attribute payload */
		writeSequence( stream, length + flagSize + \
					   ( int ) sizeofObject( dataLength ) );
		swrite( stream, attributeInfoPtr->oid,
				sizeofOID( attributeInfoPtr->oid ) );
		if( flagSize > 0 )
			writeBoolean( stream, TRUE, DEFAULT_TAG );
		if( wrapperTagSet )
			status = writeSet( stream, dataLength );
		else
			status = writeOctetStringHole( stream, dataLength, DEFAULT_TAG );
		if( cryptStatusError( status ) )
			return( status );

		/* Write the current attribute */
		for( iterationCount = 0;
			 attributeListPtr != NULL && \
				attributeListPtr->attributeID == attributeID && \
				iterationCount < FAILSAFE_ITERATIONS_MED;
			 attributeListPtr = attributeListPtr->next, iterationCount++ )
			{
			int innerIterationCount;
			
			/* Write any encapsulating SEQUENCEs if necessary, followed by
			   the field itself.  In some rare instances we may have a zero-
			   length SEQUENCE (if all the member(s) of the sequence have
			   default values) so we only try to write the member if there's
			   encoding information for it present */
			for( attributeListPtr->fifoPos = attributeListPtr->fifoEnd, \
					innerIterationCount = 0;
				 cryptStatusOK( status ) && \
					attributeListPtr->fifoPos > 0 && \
					innerIterationCount < ENCODING_FIFO_SIZE;
				 innerIterationCount++ )
				{
				status = writeAttributeField( stream, 
									( ATTRIBUTE_LIST * ) attributeListPtr,
									complianceLevel );
				}
			ENSURES( innerIterationCount < ENCODING_FIFO_SIZE );
			if( cryptStatusOK( status ) && \
				attributeListPtr->attributeInfoPtr != NULL )
				{
				status = writeAttributeField( stream, 
									( ATTRIBUTE_LIST * ) attributeListPtr,
									complianceLevel );
				}
			if( cryptStatusError( status ) )
				return( status );
			}
		ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );

		*attributeListPtrPtr = attributeListPtr;
		return( CRYPT_OK );
		}

	/* It's a blob attribute, write the header, OID, critical flag (if 
	   present), and payload wrapped up as appropriate */
	flagSize = ( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) ? \
			   sizeofBoolean() : 0;
	writeSequence( stream, sizeofOID( attributeListPtr->oid ) + flagSize + \
				   ( int ) sizeofObject( attributeListPtr->valueLength ) );
	swrite( stream, attributeListPtr->oid,
			sizeofOID( attributeListPtr->oid ) );
	if( flagSize > 0 )
		writeBoolean( stream, TRUE, DEFAULT_TAG );
	if( wrapperTagSet )
		writeSet( stream, attributeListPtr->valueLength );
	else
		{
		writeOctetStringHole( stream, attributeListPtr->valueLength, 
							  DEFAULT_TAG );
		}
	status = swrite( stream, attributeListPtr->value,
					 attributeListPtr->valueLength );
	if( cryptStatusOK( status ) )
		*attributeListPtrPtr = attributeListPtr->next;
	return( status );
	}

/****************************************************************************
*																			*
*						Attribute Collection Write Routines					*
*																			*
****************************************************************************/

/* Write a set of attributes */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeAttributes( INOUT STREAM *stream, 
					 INOUT ATTRIBUTE_LIST *attributeListPtr,
					 IN_ENUM_OPT( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type,
					 IN_LENGTH const int attributeSize )
	{
	int signUnrecognised = DUMMY_INIT, complianceLevel, iterationCount;
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );

	REQUIRES( type >= CRYPT_CERTTYPE_NONE && type < CRYPT_CERTTYPE_LAST );
			  /* Single CRL entries have the special-case type 
			     CRYPT_CERTTYPE_NONE */
	REQUIRES( attributeSize > 0 && attributeSize < MAX_INTLENGTH );

	/* Some attributes have odd encoding/handling requirements that can cause
	   problems for other software so we only enforce peculiarities required
	   by the standard at higher compliance levels.  In addition we only sign
	   unrecognised attributes if we're explicitly asked to do so by the 
	   user */
	status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
							  IMESSAGE_GETATTRIBUTE, &complianceLevel,
							  CRYPT_OPTION_CERT_COMPLIANCELEVEL );
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
								  IMESSAGE_GETATTRIBUTE, &signUnrecognised,
								  CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* CMS attributes work somewhat differently from normal attributes in 
	   that, since they're encoded as a SET OF Attribute, they have to be 
	   sorted according to their encoded form before being written.  For 
	   this reason we don't write them sorted by OID as with the other 
	   attributes but keep writing the next-lowest attribute until they've 
	   all been written */
	if( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES || \
		type == CRYPT_CERTTYPE_RTCS_REQUEST || \
		type == CRYPT_CERTTYPE_RTCS_RESPONSE )
		{
		ATTRIBUTE_LIST *currentAttributePtr;
		BYTE currentEncodedForm[ ATTR_ENCODED_SIZE + 8 ];

		/* Write the wrapper, depending on the object type */
		if( type == CRYPT_CERTTYPE_RTCS_REQUEST )
			writeSet( stream, attributeSize );
		else
			{
			writeConstructed( stream, attributeSize, 
							  ( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES ) ? \
								CTAG_SI_AUTHENTICATEDATTRIBUTES : \
								CTAG_RP_EXTENSIONS );
			}

		/* Write the attributes in sorted form */
		memset( currentEncodedForm, 0, ATTR_ENCODED_SIZE );	/* Set lowest encoded form */
		for( currentAttributePtr = getNextEncodedAttribute( attributeListPtr, \
															currentEncodedForm,
															ATTR_ENCODED_SIZE ),
				iterationCount = 0;
			 currentAttributePtr != NULL && cryptStatusOK( status ) && \
				iterationCount < FAILSAFE_ITERATIONS_LARGE;
			currentAttributePtr = getNextEncodedAttribute( attributeListPtr,
														   currentEncodedForm,
														   ATTR_ENCODED_SIZE ),
				iterationCount++ )
			{
			status = writeAttribute( stream, &currentAttributePtr, TRUE,
									 complianceLevel );
			}
		ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
		return( status );
		}

	/* Write the appropriate extensions tag for the certificate object and 
	   determine how far we can read.  CRLs and OCSP requests/responses have 
	   two extension types that have different tagging, per-entry extensions 
	   and entire-CRL/request extensions.  To differentiate between the two 
	   we write per-entry extensions with a type of CRYPT_CERTTYPE_NONE */
	switch( type )
		{
		case CRYPT_CERTTYPE_CERTIFICATE:
		case CRYPT_CERTTYPE_CRL:
			writeConstructed( stream, ( int ) sizeofObject( attributeSize ),
							  ( type == CRYPT_CERTTYPE_CERTIFICATE ) ? \
							  CTAG_CE_EXTENSIONS : CTAG_CL_EXTENSIONS );
			status = writeSequence( stream, attributeSize );
			break;

		case CRYPT_CERTTYPE_CERTREQUEST:
			writeSequence( stream, sizeofOID( OID_PKCS9_EXTREQ ) + \
						   ( int ) sizeofObject( sizeofObject( attributeSize ) ) );
			swrite( stream, OID_PKCS9_EXTREQ, sizeofOID( OID_PKCS9_EXTREQ ) );
			writeSet( stream, ( int ) sizeofObject( attributeSize ) );
			status = writeSequence( stream, attributeSize );
			break;

		case CRYPT_CERTTYPE_REQUEST_CERT:
		case CRYPT_CERTTYPE_REQUEST_REVOCATION:
			/* No wrapper, extensions are written directly */
			break;

		case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
		case CRYPT_CERTTYPE_PKIUSER:
		case CRYPT_CERTTYPE_NONE:
			status = writeSequence( stream, attributeSize );
			break;

		case CRYPT_CERTTYPE_OCSP_REQUEST:
			writeConstructed( stream, ( int ) sizeofObject( attributeSize ), 
							  CTAG_OR_EXTENSIONS );
			status = writeSequence( stream, attributeSize );
			break;

		case CRYPT_CERTTYPE_OCSP_RESPONSE:
			writeConstructed( stream, ( int ) sizeofObject( attributeSize ), 
							  CTAG_OP_EXTENSIONS );
			status = writeSequence( stream, attributeSize );
			break;

		default:
			retIntError();
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Write the known attributes until we reach either the end of the list
	   or the first blob-type attribute */
	for( iterationCount = 0;
		 cryptStatusOK( status ) && attributeListPtr != NULL && \
			!isBlobAttribute( attributeListPtr ) && \
			iterationCount < FAILSAFE_ITERATIONS_LARGE;
		 iterationCount++ )
		{
		status = writeAttribute( stream, &attributeListPtr, FALSE, 
								 complianceLevel );
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
	if( cryptStatusError( status ) || !signUnrecognised  )
		return( status );

	/* Write the blob-type attributes */
	for( iterationCount = 0;
		 attributeListPtr != NULL && cryptStatusOK( status ) && \
			iterationCount < FAILSAFE_ITERATIONS_LARGE;
		 iterationCount++ )
		{
		status = writeAttribute( stream, &attributeListPtr, FALSE, 
								 complianceLevel );
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
	return( status );
	}

⌨️ 快捷键说明

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