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

📄 asn1s_rw.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
						min( ivLength, queryInfoPtr->ivLength ) );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( createInfo.cryptHandle, 
									  IMESSAGE_SETATTRIBUTE_S, &msgData, 
									  CRYPT_CTXINFO_IV );
		}
	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, IMESSAGE_DECREFCOUNT );
		if( cryptArgError( status ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			status = CRYPT_ERROR_BADDATA;
			}
		}
	else
		*iCryptContext = createInfo.cryptHandle;
	return( status );
	}

/****************************************************************************
*																			*
*							Message Digest Routines							*
*																			*
****************************************************************************/

/* Read/write a message digest value.  This is another one of those oddball
   functions which is present here because it's the least inappropriate place
   to put it */

int writeMessageDigest( STREAM *stream, const CRYPT_ALGO_TYPE hashAlgo, 
						const void *hash, const int hashSize )
	{
	writeSequence( stream, sizeofAlgoID( hashAlgo ) + \
				   ( int ) sizeofObject( hashSize ) );
	writeAlgoID( stream, hashAlgo );
	return( writeOctetString( stream, hash, hashSize, DEFAULT_TAG ) );
	}

int readMessageDigest( STREAM *stream, CRYPT_ALGO_TYPE *hashAlgo, void *hash, 
					   int *hashSize )
	{
	readSequence( stream, NULL );
	readAlgoID( stream, hashAlgo );
	return( readOctetString( stream, hash, hashSize, CRYPT_MAX_HASHSIZE ) );
	}

/****************************************************************************
*																			*
*								CMS Header Routines							*
*																			*
****************************************************************************/

/* 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 */
	readLongSequence( stream, &totalLength );
	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 == CRYPT_UNUSED )
		{
		status = checkEOC( stream );
		if( cryptStatusError( status ) )
			return( status );
		if( status == TRUE )
			/* We've seen EOC octets, the length is the overall data 
			   length */
			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) */
		status = readLongConstructed( stream, NULL, 0 );
		if( cryptStatusError( status ) )
			return( status );
		tag = peekTag( 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 );
			}
		status = readLongGenericHole( stream, &totalLength, tag );
		if( cryptStatusError( status ) )
			return( status );
		if( dataSize != NULL )
			*dataSize = totalLength;
		}

	/* 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 that 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 */
	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 */
		writeConstructed( stream, sizeofObject( dataSize ), 0 );
		if( isOctetString )
			return( writeOctetStringHole( stream, dataSize, DEFAULT_TAG ) );
		return( writeSequence( stream, dataSize ) );
		}

	/* 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 = 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 length;
	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, NULL );
	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, which may be either primitive or constructed
	   depending on the content */
	tag = peekTag( stream );
	status = readLongGenericHole( stream, &length, tag );
	if( cryptStatusOK( status ) && \
		( 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, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	queryInfoPtr->size = length;

	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 = 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 );
		writeOctetStringHole( stream, dataSize, MAKE_CTAG_PRIMITIVE( 0 ) );
		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 + -