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

📄 asn1_ext.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
			RESOURCE_DATA msgData;

			setMessageData( &msgData, queryInfoPtr->iv, 
							min( ivLength, queryInfoPtr->ivLength ) );
			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 )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
			hashAlgo <= CRYPT_ALGO_LAST_HASH );
	assert( isReadPtr( hash, 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 )
	{
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( hash, 16 ) );
	assert( isWritePtr( hashSize, sizeof( int ) ) );

	/* Clear the return values */
	memset( hash, 0, 16 );
	*hashSize = 0;

	/* Read the message digest, enforcing sensible size values */
	readSequence( stream, NULL );
	status = readAlgoID( stream, hashAlgo );
	if( cryptStatusError( status ) )
		return( status );
	status = readOctetString( stream, hash, hashSize, CRYPT_MAX_HASHSIZE );
	if( cryptStatusOK( status ) && \
		( *hashSize < 16 || *hashSize > CRYPT_MAX_HASHSIZE ) )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		status = CRYPT_ERROR_BADDATA;
		}
	return( status );
	}

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

/* Read and write CMS headers.  When reading CMS headers we check a bit more
   than just the header OID, which means that we need to provide additional
   information alongside the OID information.  This is provided as 
   CMS_CONTENT_INFO in the OID info extra data field */

int readCMSheader( STREAM *stream, const OID_INFO *oidInfo, long *dataSize, 
				   const BOOLEAN isInnerHeader )
	{
	const OID_INFO *oidInfoPtr;
	BOOLEAN isData = FALSE;
	long length, value;
	int tag, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( oidInfo, sizeof( OID_INFO ) ) );
	assert( dataSize == NULL || isWritePtr( dataSize, sizeof( long ) ) );

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

	/* Read the outer SEQUENCE and OID.  We can't use a normal 
	   readSequence() here because the data length could be much longer than 
	   the maximum allowed in the readSequence() sanity check */
	readLongSequence( stream, &length );
	status = readOIDEx( stream, oidInfo, &oidInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* If the content type is data, the content is an OCTET STRING rather
	   than a SEQUENCE so we remember the type for later */
	if( sizeofOID( oidInfoPtr->oid ) == sizeofOID( OID_CMS_DATA ) && \
		!memcmp( oidInfoPtr->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( length == CRYPT_UNUSED )
		{
		status = checkEOC( stream );
		if( cryptStatusError( status ) )
			return( status );
		if( status == TRUE )
			/* We've seen EOC octets, the item has zero length (for example 
			   with a detached signature), we're done */
			return( CRYPT_OK );
		}

	/* If the content is supplied externally (for example with a detached
	   signature), denoted by the fact that the total content consists only
	   of the OID, we're done */
	if( length != CRYPT_UNUSED && length <= sizeofOID( oidInfoPtr->oid ) )
		return( oidInfoPtr->selectionID );

	/* 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 ) )
		return( sSetError( stream, status ) );
	status = readLongGenericHole( stream, &length, tag );
	if( cryptStatusError( status ) )
		return( status );
	if( dataSize != NULL )
		*dataSize = length;

	/* If it's structured (i.e. not data in an OCTET STRING), check the 
	   version number of the content if required */
	if( !isData && oidInfoPtr->extraInfo != NULL )
		{
		const CMS_CONTENT_INFO *contentInfoPtr = oidInfoPtr->extraInfo;

		status = readShortInteger( stream, &value );
		if( cryptStatusError( status ) )
			return( status );
		if( value < contentInfoPtr->minVersion || \
			value > contentInfoPtr->maxVersion )
			return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
		}

	return( oidInfoPtr->selectionID );
	}

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

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( contentOID, sizeofOID( contentOID ) ) );

	/* 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( contentOID ) == 12 && \
		!memcmp( contentOID, OID_MS_SPCINDIRECTDATACONTEXT, 12 ) )
		isOctetString = FALSE;

	/* If a size is given, write the definite form */
	if( dataSize != CRYPT_UNUSED )
		{
		writeSequence( stream, sizeofOID( contentOID ) + ( ( dataSize ) ? \
					   ( int ) sizeofObject( sizeofObject( dataSize ) ) : 0 ) );
		writeOID( stream, contentOID );
		if( dataSize <= 0 )
			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, contentOID );
	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;

	assert( isReadPtr( contentOID, sizeofOID( contentOID ) ) );
	assert( isHandleRangeValid( iCryptContext ) );

	/* 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 (the size 2 is for the tag + 0x80
	   indefinite-length indicator) */
	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_INFO *oidInfo,
					   CRYPT_CONTEXT *iCryptContext, QUERY_INFO *queryInfo )
	{
	QUERY_INFO localQueryInfo, *queryInfoPtr = ( queryInfo == NULL ) ? \
											   &localQueryInfo : queryInfo;
	long length;
	int selectionID, tag, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( oidInfo, sizeof( OID_INFO ) ) );
	assert( iCryptContext == NULL || \
			isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
	assert( queryInfo == NULL || \
			isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );

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

	/* Read the outer SEQUENCE, OID, and AlgorithmIdentifier.  We can't use 
	   a normal readSequence() here because the data length could be much 
	   longer than the maximum allowed in the readSequence() sanity check */
	readLongSequence( stream, NULL );
	status = readOID( stream, oidInfo, &selectionID );
	if( cryptStatusOK( status ) )
		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( selectionID );
	}

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

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( contentOID, sizeofOID( contentOID ) ) );
	assert( isHandleRangeValid( iCryptContext ) );

	/* 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 );
		if( cryptStatusError( status ) )
			return( status );
		return( writeOctetStringHole( stream, dataSize, \
									  MAKE_CTAG_PRIMITIVE( 0 ) ) );
		}

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

⌨️ 快捷键说明

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