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

📄 asn1_ext.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
	BYTE iv[ CRYPT_MAX_IVSIZE ];
	CRYPT_ALGO_TYPE algorithm;
	CRYPT_MODE_TYPE mode;
	int oidSize, ivSize = 0, sizeofIV = 0, paramSize, status;

	/* Extract the information that we need to write the 
	   AlgorithmIdentifier */
	status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, 
							  &algorithm, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, 
								  &mode, CRYPT_CTXINFO_MODE );
	if( cryptStatusOK( status ) && !isStreamCipher( algorithm ) && \
		needsIV( mode ) )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, iv, CRYPT_MAX_IVSIZE );
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_CTXINFO_IV );
#if 0	/* 18/4/04 No longer needed since IV is always set */
		if( status == CRYPT_ERROR_NOTINITED && sIsNullStream( stream ) )
			/* If we're just doing a length check there may not be an IV set
			   yet, so we just use dummy data */
			status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, 
									  &ivSize, CRYPT_CTXINFO_IVSIZE );
		else
#endif /* 0 */
		ivSize = msgData.length;
		sizeofIV = ( int ) sizeofObject( ivSize );
		}
	if( cryptStatusError( status ) )
		{
		assert( NOTREACHED );
		return( status );
		}
	if( ( oid = algorithmToOIDcheck( algorithm, 
									 ( CRYPT_ALGO_TYPE ) mode ) ) == NULL )
		/* Some algorithm+mode combinations can't be encoded using the
		   available PKCS #7 OIDs, the best that we can do is return a 
		   CRYPT_ERROR_NOTAVAIL */
		return( CRYPT_ERROR_NOTAVAIL );
	oidSize = sizeofOID( oid );

	/* Write the algorithm-specific parameters */
	switch( algorithm )
		{
		case CRYPT_ALGO_3DES:
		case CRYPT_ALGO_AES:
		case CRYPT_ALGO_BLOWFISH:
		case CRYPT_ALGO_DES:
			{
			const int noBits = ( algorithm == CRYPT_ALGO_AES ) ? 128 : 64;

			paramSize = ( mode == CRYPT_MODE_ECB ) ? sizeofNull() : \
				( ( mode == CRYPT_MODE_CBC ) || \
				  ( algorithm == CRYPT_ALGO_AES && mode == CRYPT_MODE_OFB ) ) ? \
				  sizeofIV : \
				  ( int ) sizeofObject( sizeofIV + sizeofShortInteger( noBits ) );
			writeSequence( stream, oidSize + paramSize );
			if( algorithm == CRYPT_ALGO_AES )
				{
				int keySize;

				/* AES uses a somewhat odd encoding in which the last byte 
				   of the OID jumps in steps of 20 depending on the key 
				   size, so we adjust the OID that we actually write based 
				   on the key size.  It's somewhat unlikely that any 
				   implementation actually cares about this since the size 
				   information is always communicated anderswhere, but we do 
				   it just in case */
				krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, 
								 &keySize, CRYPT_CTXINFO_KEYSIZE );
				swrite( stream, oid, oidSize - 1 );
				sputc( stream, oid[ oidSize - 1 ] + \
							   ( ( keySize == 16 ) ? 0 : \
								 ( keySize == 24 ) ? 20 : 40 ) );
				}
			else
				swrite( stream, oid, oidSize );
			if( mode == CRYPT_MODE_ECB )
				return( writeNull( stream, DEFAULT_TAG ) );
			if( ( mode == CRYPT_MODE_CBC ) || \
				( algorithm == CRYPT_ALGO_AES && mode == CRYPT_MODE_OFB ) )
				return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );
			writeSequence( stream, sizeofIV + sizeofShortInteger( noBits ) );
			writeOctetString( stream, iv, ivSize, DEFAULT_TAG );
			return( writeShortInteger( stream, noBits, DEFAULT_TAG ) );
			}

		case CRYPT_ALGO_CAST:
			paramSize = sizeofIV + sizeofShortInteger( 128 );
			writeSequence( stream, oidSize + \
								   ( int ) sizeofObject( paramSize ) );
			swrite( stream, oid, oidSize );
			writeSequence( stream, paramSize );
			writeOctetString( stream, iv, ivSize, DEFAULT_TAG );
			return( writeShortInteger( stream, 128, DEFAULT_TAG ) );

		case CRYPT_ALGO_IDEA:
			paramSize = ( mode == CRYPT_MODE_ECB ) ? \
						sizeofNull() : \
						( int ) sizeofObject( sizeofIV );
			writeSequence( stream, oidSize + paramSize );
			swrite( stream, oid, oidSize );
			if( mode == CRYPT_MODE_ECB )
				return( writeNull( stream, DEFAULT_TAG ) );
			writeSequence( stream, sizeofIV );
			return( writeOctetString( stream, iv, ivSize, \
									  ( mode == CRYPT_MODE_CFB ) ? \
										3 : DEFAULT_TAG ) );

		case CRYPT_ALGO_RC2:
			paramSize = ( ( mode == CRYPT_MODE_ECB ) ? 0 : sizeofIV ) + \
						sizeofShortInteger( RC2_KEYSIZE_MAGIC );
			writeSequence( stream, oidSize + \
								   ( int ) sizeofObject( paramSize ) );
			swrite( stream, oid, oidSize );
			writeSequence( stream, paramSize );
			if( mode != CRYPT_MODE_CBC )
				return( writeShortInteger( stream, RC2_KEYSIZE_MAGIC, 
										   DEFAULT_TAG ) );
			writeShortInteger( stream, RC2_KEYSIZE_MAGIC, DEFAULT_TAG );
			return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );

		case CRYPT_ALGO_RC4:
			writeSequence( stream, oidSize + sizeofNull() );
			swrite( stream, oid, oidSize );
			return( writeNull( stream, DEFAULT_TAG ) );

		case CRYPT_ALGO_RC5:
			paramSize = sizeofShortInteger( 16 ) + \
						sizeofShortInteger( 12 ) + \
						sizeofShortInteger( 64 ) + \
						sizeofIV;
			writeSequence( stream, oidSize + \
								   ( int ) sizeofObject( paramSize ) );
			swrite( stream, oid, oidSize );
			writeSequence( stream, paramSize );
			writeShortInteger( stream, 16, DEFAULT_TAG );	/* Version */
			writeShortInteger( stream, 12, DEFAULT_TAG );	/* Rounds */
			writeShortInteger( stream, 64, DEFAULT_TAG );	/* Block size */
			return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );

		case CRYPT_ALGO_SKIPJACK:
			writeSequence( stream, oidSize + \
								   ( int ) sizeofObject( sizeofIV ) );
			swrite( stream, oid, oidSize );
			writeSequence( stream, sizeofIV );
			return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

/****************************************************************************
*																			*
*							AlgorithmIdentifier Routines					*
*																			*
****************************************************************************/

/* Because AlgorithmIdentifiers are only defined for a subset of the
   algorithms that cryptlib supports, we have to check that the algorithm
   and mode being used can be represented in encoded data before we try to
   do anything with it */

BOOLEAN checkAlgoID( const CRYPT_ALGO_TYPE algorithm, 
					 const CRYPT_MODE_TYPE mode )
	{
	return( ( algorithmToOIDcheck( algorithm, \
						( CRYPT_ALGO_TYPE ) mode ) != NULL ) ? TRUE : FALSE );
	}

/* Determine the size of an AlgorithmIdentifier record */

int sizeofAlgoIDex( const CRYPT_ALGO_TYPE algorithm, 
					const CRYPT_ALGO_TYPE subAlgorithm,
					const int extraLength )
	{
	const BYTE *oid = algorithmToOID( algorithm, subAlgorithm );

	if( oid == NULL )
		{
		assert( NOTREACHED );
		return( 0 );
		}
	return( ( int ) sizeofObject( sizeofOID( oid ) + \
								  ( ( extraLength > 0 ) ? extraLength : \
														  sizeofNull() ) ) );
	}

int sizeofAlgoID( const CRYPT_ALGO_TYPE algorithm )
	{
	return( sizeofAlgoIDex( algorithm, CRYPT_ALGO_NONE, 0 ) );
	}

/* Write an AlgorithmIdentifier record */

int writeAlgoIDex( STREAM *stream, const CRYPT_ALGO_TYPE algorithm,
				   const CRYPT_ALGO_TYPE subAlgorithm, const int extraLength )
	{
	const BYTE *oid = algorithmToOID( algorithm, subAlgorithm );
	int status;

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

	if( oid == NULL )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_WRITE );
		}

	/* Write the AlgorithmIdentifier field */
	writeSequence( stream, sizeofOID( oid ) + \
				   ( ( extraLength > 0 ) ? extraLength : sizeofNull() ) );
	status = swrite( stream, oid, sizeofOID( oid ) );
	if( extraLength <= 0 )
		/* No extra parameters so we need to write a NULL */
		status = writeNull( stream, DEFAULT_TAG );

	return( status );
	}

int writeAlgoID( STREAM *stream, const CRYPT_ALGO_TYPE algorithm  )
	{
	return( writeAlgoIDex( stream, algorithm, CRYPT_ALGO_NONE, 0 ) );
	}

/* Read an AlgorithmIdentifier record */

int readAlgoIDex( STREAM *stream, CRYPT_ALGO_TYPE *algorithm, 
				  CRYPT_ALGO_TYPE *subAlgorithm, int *extraLength )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( algorithm == NULL || \
			isWritePtr( algorithm, sizeof( CRYPT_ALGO_TYPE ) ) );
	assert( subAlgorithm == NULL || \
			isWritePtr( subAlgorithm, sizeof( CRYPT_ALGO_TYPE ) ) );
	assert( extraLength == NULL || \
			isWritePtr( extraLength, sizeof( int ) ) );

	return( readAlgoIDheader( stream, algorithm, subAlgorithm, extraLength,
							  DEFAULT_TAG ) );
	}

int readAlgoID( STREAM *stream, CRYPT_ALGO_TYPE *algorithm )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( algorithm == NULL || \
			isWritePtr( algorithm, sizeof( CRYPT_ALGO_TYPE ) ) );

	return( readAlgoIDheader( stream, algorithm, NULL, NULL, DEFAULT_TAG ) );
	}

/* Determine the size of an AlgorithmIdentifier record from an encryption
   context */

int sizeofContextAlgoID( const CRYPT_CONTEXT iCryptContext,
						 const CRYPT_ALGO_TYPE subAlgorithm, 
						 const int flags )
	{
	int cryptAlgo, status;

	assert( isHandleRangeValid( iCryptContext ) );

	/* If it's a standard write, determine how large the algoID and 
	   parameters are.  Because this is a rather complex operation, the
	   easiest way to do it is to write to a null stream and get its
	   size */
	if( flags == ALGOID_FLAG_NONE )
		{
		STREAM nullStream;

		sMemOpen( &nullStream, NULL, 0 );
		status = writeContextAlgoID( &nullStream, iCryptContext, 
									 subAlgorithm, ALGOID_FLAG_NONE );
		if( cryptStatusOK( status ) )
			status = stell( &nullStream );
		sMemClose( &nullStream );
		return( status );
		}

	assert( flags == ALGOID_FLAG_ALGOID_ONLY );

	/* Write the algoID only */
	status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );
	return( sizeofAlgoIDex( cryptAlgo, subAlgorithm, 0 ) );
	}

/* Write an AlgorithmIdentifier record from an encryption context */

int writeContextAlgoID( STREAM *stream, const CRYPT_CONTEXT iCryptContext,
						const CRYPT_ALGO_TYPE subAlgorithm, 
						const int flags )
	{
	int cryptAlgo, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isHandleRangeValid( iCryptContext ) );

	status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );
	if( flags & ALGOID_FLAG_ALGOID_ONLY )
		return( writeAlgoIDex( stream, cryptAlgo, subAlgorithm, 0 ) );

	/* If we're writing parameters such as key and block sizes and IVs
	   alongside the algorithm identifier, it has to be a conventional
	   context */
	assert( subAlgorithm == CRYPT_ALGO_NONE );
	assert( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
			cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL );

	return( writeContextCryptAlgoID( stream, iCryptContext ) );
	}

/* Turn an AlgorithmIdentifier into a hash/encryption context */

int readContextAlgoID( STREAM *stream, CRYPT_CONTEXT *iCryptContext,
					   QUERY_INFO *queryInfo, const int tag )
	{
	QUERY_INFO localQueryInfo, *queryInfoPtr = ( queryInfo == NULL ) ? \
											   &localQueryInfo : queryInfo;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int status;

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

	/* Read the algorithm info.  If we're not creating a context from the
	   info, we're done */
	if( iCryptContext != NULL )
		*iCryptContext = CRYPT_ERROR;
	status = readAlgoIDInfo( stream, queryInfoPtr, tag );
	if( cryptStatusError( status ) || iCryptContext == NULL )
		{
		if( status == CRYPT_ERROR_BADDATA || status == CRYPT_ERROR_UNDERFLOW )
			/* It's a stream-related error, make it persistent */
			sSetError( stream, status );
		return( status );
		}

	/* Create the object from it */
	setMessageCreateObjectInfo( &createInfo, queryInfoPtr->cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	if( queryInfoPtr->cryptAlgo > CRYPT_ALGO_LAST_CONVENTIONAL )
		{
		/* If it's not a conventional encryption algorithm, we're done */
		*iCryptContext = createInfo.cryptHandle;
		return( CRYPT_OK );
		}
	status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
							  &queryInfoPtr->cryptMode, CRYPT_CTXINFO_MODE );
	if( cryptStatusOK( status ) && \
		!isStreamCipher( queryInfoPtr->cryptAlgo ) )
		{
		int ivLength;

		status = krnlSendMessage( createInfo.cryptHandle, 
								  IMESSAGE_GETATTRIBUTE, &ivLength, 
								  CRYPT_CTXINFO_IVSIZE );
		if( cryptStatusOK( status ) )
			{

⌨️ 快捷键说明

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