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

📄 asn1oid.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		}
	if( cryptStatusError( status ) )
		{
		/* If there's an error in the parameters stored with the key we'll 
		   get an arg or attribute error when we try to set the attribute so 
		   we translate it into an error code which is appropriate for the 
		   situation.  In addition since this is (arguably) a stream format
		   error (the data read from the stream is invalid), we also set the
		   stream status */
		krnlSendNotifier( createInfo.cryptHandle, 
						  RESOURCE_IMESSAGE_DECREFCOUNT );
		if( cryptArgError( status ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			status = CRYPT_ERROR_BADDATA;
			}
		}
	else
		*iCryptContext = createInfo.cryptHandle;
	return( status );
	}

/****************************************************************************
*																			*
*							Read/Write CMS Headers							*
*																			*
****************************************************************************/

/* Read an abnormally-long SEQUENCE header.  This is used in place of the
   usual readSequence() in places where potentially huge data quantities 
   would fail the sanity check enforced by readSequence() */

static long readLongSequence( STREAM *stream )
	{
	int tag;

	tag = readTag( stream );
	if( cryptStatusError( tag ) )
		return( tag );
	if( tag != BER_SEQUENCE )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( CRYPT_ERROR_BADDATA );
		}
	return( readLength( stream ) );
	}

/* Read and write CMS headers */

int readCMSheader( STREAM *stream, const OID_SELECTION *oidSelection,
				   long *dataSize, const BOOLEAN isInnerHeader )
	{
	BOOLEAN isData = FALSE;
	BYTE oid[ MAX_OID_SIZE ];
	long totalLength, value;
	int length, oidEntry, status;

	/* Clear return value */
	if( dataSize != NULL )
		*dataSize = 0;

	/* Read the outer SEQUENCE and OID and try and find the entry for the 
	   OID.  Note that we can't use a normal readSequence() here since the 
	   data length could be much longer than the maximum allowed in the 
	   readSequence() sanity check.  In addition we can't use 
	   readOIDSelection() either since we have to identify and handle data 
	   vs non-data content in different ways */
	totalLength = readLongSequence( stream );
	status = readRawObject( stream, oid, &length, MAX_OID_SIZE,
							BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );
	for( oidEntry = 0; oidSelection[ oidEntry ].oid != NULL; oidEntry++ )
		if( length == sizeofOID( oidSelection[ oidEntry ].oid ) && \
			!memcmp( oid, oidSelection[ oidEntry ].oid, length ) )
			break;
	if( oidSelection[ oidEntry ].oid == NULL )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( CRYPT_ERROR_BADDATA );
		}

	/* If the content type is data, the content is an OCTET STRING rather
	   than a SEQUENCE so we remember the type for later */
	if( length == sizeofOID( OID_CMS_DATA ) && \
		!memcmp( oid, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) ) )
		isData = TRUE;

	/* Some Microsoft software produces an indefinite encoding for a single
	   OID so we have to check for this */
	if( !totalLength && checkEOC( stream ) )
		totalLength = length;

	/* If the content is supplied externally (for example with a detached
	   sig), there won't be any content present */
	if( totalLength == length )
		{
		if( dataSize != NULL )
			*dataSize = 0;
		}
	else
		{
		int tag;

		/* Read the content [0] tag and OCTET STRING/SEQUENCE (this requires 
		   some special-case handling, see the comment in writeCMSHeader() 
		   for more details).  Note that we can't use readConstructed() here 
		   because that's only intended for short data objects and will 
		   report an error with large amounts of encapsulated data */
		tag = readTag( stream );
		status = ( int ) readLength( stream );
		if( cryptStatusError( status ) )
			return( status );
		if( tag != MAKE_CTAG( 0 ) )
			status = CRYPT_ERROR_BADDATA;
		else
			{
			tag = readTag( stream );
			if( isData )
				{
				/* It's pure data content, it must be an OCTET STRING */
				if( tag != BER_OCTETSTRING && \
					tag != ( BER_OCTETSTRING | BER_CONSTRUCTED ) )
					status = CRYPT_ERROR_BADDATA;
				}
			else
				if( isInnerHeader )
					{
					/* It's an inner header, it should be an OCTET STRING
					   but alternative interpretations are possible based
					   on the PKCS #7 definition of inner content */
					if( tag != BER_OCTETSTRING && \
						tag != ( BER_OCTETSTRING | BER_CONSTRUCTED ) && \
						tag != BER_SEQUENCE )
						status = CRYPT_ERROR_BADDATA;
					}
				else
					/* It's an outer header containing other than data, it
					   must be a SEQUENCE */
					if( tag != BER_SEQUENCE )
						status = CRYPT_ERROR_BADDATA;
			}
		if( cryptStatusError( status ) )
			{
			sSetError( stream, status );
			return( status );
			}
		value = readLength( stream );
		if( cryptStatusError( value ) )
			return( ( int ) value );
		if( dataSize != NULL )
			*dataSize = ( value ) ? value : CRYPT_UNUSED;
		}

	/* If it's not data in an OCTET STRING, check the version number of the
	   content if required */
	if( !isData && oidSelection[ oidEntry ].minVersion != CRYPT_UNUSED )
		{
		readShortInteger( stream, &value );
		if( value < oidSelection[ oidEntry ].minVersion || \
			value > oidSelection[ oidEntry ].maxVersion )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( CRYPT_ERROR_BADDATA );
			}
		}

	return( sStatusOK( stream ) ? oidSelection[ oidEntry ].selection : \
								  sGetStatus( stream ) );
	}

int writeCMSheader( STREAM *stream, const BYTE *oid, const long dataSize,
					const BOOLEAN isInnerHeader )
	{
	BOOLEAN isOctetString = ( isInnerHeader || \
							  ( sizeofOID( oid ) == 11 && \
							  !memcmp( oid, OID_CMS_DATA, 11 ) ) ) ? \
							TRUE : FALSE;

	/* The handling of the wrapper type for the content is rather complex.
	   If it's an outer header, it's an OCTET STRING for data and a SEQUENCE
	   for everything else.  If it's an inner header it usually follows the
	   same rule, however for signed data the content was changed from

		content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL

	   in PKCS #7 to

		eContent [0] EXPLICIT OCTET STRING OPTIONAL

	   for CMS (it was always an OCTET STRING for encrypted data).  To
	   complicate things, there are some older implementations based on the 
	   PKCS #7 interpretation which use a SEQUENCE (namely AuthentiCode).
	   To resolve this, we use an OCTET STRING for inner content unless the
	   content type is spcIndirectDataContext */
	if( isInnerHeader && sizeofOID( oid ) == 12 && \
		!memcmp( oid, OID_MS_SPCINDIRECTDATACONTEXT, 12 ) )
		isOctetString = FALSE;

	/* If a size is given, write the definite form.  Note that we can't use
	   any of the more useful functions like writeConstructed() or 
	   writeGenericHole() since the length could be larger than the safe 
	   upper limit enforced by these functions */
	if( dataSize != CRYPT_UNUSED )
		{
		writeSequence( stream, sizeofOID( oid ) + ( ( dataSize ) ? \
					   ( int ) sizeofObject( sizeofObject( dataSize ) ) : 0 ) );
		writeOID( stream, oid );
		if( !dataSize )
			return( CRYPT_OK );	/* No content, exit */
		writeCtag( stream, 0 );
		writeLength( stream, sizeofObject( dataSize ) );
		writeTag( stream, isOctetString ? BER_OCTETSTRING : BER_SEQUENCE );
		writeLength( stream, dataSize );
		return( sGetStatus( stream ) );
		}

	/* No size given, write the indefinite form */
	writeSequenceIndef( stream );
	writeOID( stream, oid );
	writeCtag0Indef( stream );
	return( isOctetString ? writeOctetStringIndef( stream ) : \
							writeSequenceIndef( stream ) );
	}

/* Read and write an encryptedContentInfo header.  The inner content may be
   implicitly or explicitly tagged depending on the exact content type */

int sizeofCMSencrHeader( const BYTE *contentOID, const long dataSize,
						 const CRYPT_CONTEXT iCryptContext )
	{
	STREAM nullStream;
	int status, cryptInfoSize;

	/* Determine the encoded size of the AlgorithmIdentifier */
	sMemOpen( &nullStream, NULL, 0 );
	status = writeContextCryptAlgoID( &nullStream, iCryptContext );
	cryptInfoSize = ( int ) stell( &nullStream );
	sMemClose( &nullStream );
	if( cryptStatusError( status ) )
		return( status );

	/* Calculate encoded size of SEQUENCE + OID + AlgoID + [0] for the
	   definite or indefinite forms */
	if( dataSize != CRYPT_UNUSED )
		return( ( int ) ( sizeofObject( sizeofOID( contentOID ) + \
				cryptInfoSize + sizeofObject( dataSize ) ) - dataSize ) );
	return( 2 + sizeofOID( contentOID ) + cryptInfoSize + 2 );
	}

int readCMSencrHeader( STREAM *stream, const OID_SELECTION *oidSelection,
					   CRYPT_CONTEXT *iCryptContext, QUERY_INFO *queryInfo )
	{
	QUERY_INFO localQueryInfo, *queryInfoPtr = ( queryInfo == NULL ) ? \
											   &localQueryInfo : queryInfo;
	long value;
	int oidEntry, tag, status;

	/* Clear the return values */
	if( iCryptContext != NULL )
		*iCryptContext = CRYPT_ERROR;
	memset( queryInfoPtr, 0, sizeof( QUERY_INFO ) );

	/* Read the outer SEQUENCE and OID.  Note that we can't use a normal
	   readSequence() here since the data length could be much longer 
	   than the maximum allowed in the readSequence() sanity check */
	readLongSequence( stream );
	status = readOIDSelection( stream, oidSelection, &oidEntry );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the AlgorithmIdentifier.  This can return non-stream-related
	   errors so if there's an error at this point we exit immediately */
	status = readContextAlgoID( stream, iCryptContext, queryInfoPtr, 
								DEFAULT_TAG );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the content [0] tag.  As with reading a standard CMS header, we
	   can't use readConstructed() because it treats the presence of 
	   unexpectedly large data quantities as an error */
	tag = readTag( stream );
	value = readLength( stream );
	if( cryptStatusError( value ) )
		status = ( int ) value;
	else
		if( tag != MAKE_CTAG( 0 ) && tag != MAKE_CTAG_PRIMITIVE( 0 ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			status = CRYPT_ERROR_BADDATA;
			}
	if( cryptStatusError( status ) )
		{
		if( iCryptContext != NULL )
			krnlSendNotifier( *iCryptContext, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
		return( status );
		}
	queryInfoPtr->size = ( value ) ? value : CRYPT_UNUSED;

	return( oidEntry );
	}

int writeCMSencrHeader( STREAM *stream, const BYTE *contentOID,
						const long dataSize,
						const CRYPT_CONTEXT iCryptContext )
	{
	STREAM nullStream;
	int cryptInfoSize, status;

	/* Determine the encoded size of the AlgorithmIdentifier */
	sMemOpen( &nullStream, NULL, 0 );
	status = writeContextCryptAlgoID( &nullStream, iCryptContext );
	cryptInfoSize = ( int ) stell( &nullStream );
	sMemClose( &nullStream );
	if( cryptStatusError( status ) )
		return( status );

	/* If a size is given, write the definite form */
	if( dataSize != CRYPT_UNUSED )
		{
		writeSequence( stream, sizeofOID( contentOID ) + cryptInfoSize + \
					   ( int ) sizeofObject( dataSize ) );
		writeOID( stream, contentOID );
		status = writeContextCryptAlgoID( stream, iCryptContext );
		writeCtagPrimitive( stream, 0 );
		writeLength( stream, dataSize );

		return( status );
		}

	/* No size given, write the indefinite form */
	writeSequenceIndef( stream );
	writeOID( stream, contentOID );
	status = writeContextCryptAlgoID( stream, iCryptContext );
	writeCtag0Indef( stream );

	return( status );
	}

⌨️ 快捷键说明

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