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

📄 asn1s_rw.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
			}

	return( CRYPT_ERROR );
	}

/* Map an algorithm and optional sub-algorithm to an OID.  These functions
   are almost identical, the only difference is that the one used for
   checking only doesn't throw an exception when it encounters an algorithm
   value that it can't encode as an OID */

static const BYTE *algorithmToOID( const CRYPT_ALGO_TYPE algorithm, 
								   const CRYPT_ALGO_TYPE subAlgorithm )
	{
	int i;

	for( i = 0; algoIDmap[ i ].algorithm != CRYPT_ALGO_NONE; i++ )
		if( algoIDmap[ i ].algorithm == algorithm && \
			algoIDmap[ i ].subAlgorithm == subAlgorithm )
			return( algoIDmap[ i ].oid );

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

static const BYTE *algorithmToOIDcheck( const CRYPT_ALGO_TYPE algorithm, 
										const CRYPT_ALGO_TYPE subAlgorithm )
	{
	int i;

	for( i = 0; algoIDmap[ i ].algorithm != CRYPT_ALGO_NONE; i++ )
		if( algoIDmap[ i ].algorithm == algorithm && \
			algoIDmap[ i ].subAlgorithm == subAlgorithm )
			return( algoIDmap[ i ].oid );

	return( NULL );
	}

int readOID( STREAM *stream, const BYTE *oid )
	{
	BYTE buffer[ MAX_OID_SIZE ];
	int dummy, status;

	status = readRawObject( stream, buffer, &dummy, MAX_OID_SIZE,
							BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) || \
		memcmp( buffer, oid, sizeofOID( oid ) ) )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		status = CRYPT_ERROR_BADDATA;
		}

	return( status );
	}

int readOIDSelection( STREAM *stream, const OID_SELECTION *oidSelection, 
					  int *selection )
	{
	BYTE buffer[ MAX_OID_SIZE ];
	int length, oidEntry, status;

	/* Read the OID data */
	status = readRawObject( stream, buffer, &length, MAX_OID_SIZE,
							BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );

	/* Try and find the entry for the OID */
	for( oidEntry = 0; oidSelection[ oidEntry ].oid != NULL; oidEntry++ )
		if( length == sizeofOID( oidSelection[ oidEntry ].oid ) && \
			!memcmp( buffer, oidSelection[ oidEntry ].oid, length ) )
			break;
	if( oidSelection[ oidEntry ].oid == NULL )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		status = CRYPT_ERROR_BADDATA;
		}
	if( selection != NULL )
		*selection = oidSelection[ oidEntry ].selection;
	
	return( status );
	}

/****************************************************************************
*																			*
*					EncryptionAlgorithmIdentifier Routines					*
*																			*
****************************************************************************/

/* EncryptionAlgorithmIdentifier parameters:

	aesXcbc, aesXofb: AES FIPS

		iv				OCTET STRING SIZE (16)

	aesXcfb: AES FIPS

		SEQUENCE {
			iv			OCTET STRING SIZE (16),
			noOfBits	INTEGER (128)
			}

	cast5cbc: RFC 2144
		SEQUENCE {
			iv			OCTET STRING DEFAULT 0,
			keyLen		INTEGER (128)
			}

	blowfishCBC, desCBC, desEDE3-CBC: Blowfish RFC/OIW
		iv				OCTET STRING SIZE (8)

	blowfishCFB, blowfishOFB, desCFB, desOFB: Blowfish RFC/OIW
		SEQUENCE {
			iv			OCTET STRING SIZE (8),
			noBits		INTEGER (64)
			}

	ideaCBC: Ascom Tech
		SEQUENCE {
			iv			OCTET STRING OPTIONAL
			}

	ideaCFB: Ascom Tech
		SEQUENCE {
			r	  [ 0 ]	INTEGER DEFAULT 64,
			k	  [ 1 ]	INTEGER DEFAULT 64,
			j	  [ 2 ]	INTEGER DEFAULT 64,
			iv	  [ 3 ]	OCTET STRING OPTIONAL
			}

	ideaOFB: Ascom Tech
		SEQUENCE {
			j			INTEGER DEFAULT 64,
			iv			OCTET STRING OPTIONAL
			}

	rc2CBC: RFC 2311
		SEQUENCE {
			rc2Param	INTEGER (58),	-- 128 bit key
			iv			OCTET STRING SIZE (8)
			}

	rc4: RFC 2311
		NULL

	rc5: RFC 2040
		SEQUENCE {
			version		INTEGER (16),
			rounds		INTEGER (12),
			blockSize	INTEGER (64),
			iv			OCTET STRING OPTIONAL
			}

	skipjackCBC: SDN.701
		SEQUENCE {
			iv			OCTET STRING
			}

   Because of the haphazard and arbitrary nature of encryption 
   AlgorithmIdentifier definitions, we can only handle the following 
   algorithm/mode combinations:

	AES ECB, CBC, CFB, OFB
	Blowfish ECB, CBC, CFB, OFB
	CAST128 CBC
	DES ECB, CBC, CFB, OFB
	3DES ECB, CBC, CFB, OFB
	IDEA ECB, CBC, CFB, OFB
	RC2 ECB, CBC
	RC4
	RC5 CBC
	Skipjack CBC */

/* Magic value to denote 128-bit RC2 keys */

#define RC2_KEYSIZE_MAGIC		58

/* Read an EncryptionAlgorithmIdentifier record */

static int readAlgoIDInfo( STREAM *stream, QUERY_INFO *queryInfo, 
						   const int tag )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	BYTE buffer[ MAX_OID_SIZE ];
	int length, bufferLength, cryptMode, status;

	/* Read the AlgorithmIdentifier header and OID */
	if( tag == DEFAULT_TAG )
		readSequence( stream, &length );
	else
		readConstructed( stream, &length, tag );
	status = readRawObject( stream, buffer, &bufferLength, MAX_OID_SIZE, 
							BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );
	if( ( cryptAlgo = oidToAlgorithm( buffer, &cryptMode ) ) == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTAVAIL );
	queryInfo->cryptAlgo = cryptAlgo;
	queryInfo->cryptMode = cryptMode;
	length -= bufferLength;

	/* Non-conventional-encryption algorithms will either have NULL 
	   parameters or none at all depending on which interpreation of which
	   standard the sender used, so if it's not a conventional encryption
	   algorithm we just skip any remaining parameter data and return */
	if( queryInfo->cryptAlgo < CRYPT_ALGO_FIRST_CONVENTIONAL || \
		queryInfo->cryptAlgo > CRYPT_ALGO_LAST_CONVENTIONAL )
		return( ( length > 0 ) ? sSkip( stream, length ) : CRYPT_OK );

	/* Read the algorithm parameters.  In theory we should do something with 
	   some of the values like the IV size parameter, but since the standard 
	   never explains what to do if it's something other than the algorithm 
	   block size (Left pad? Right pad? Sign-extend? Repeat the data?) it's 
	   safer not to do anything ("Never check for an error you don't know how 
	   to handle").  In any case there are no known cases of these strange 
	   values ever being used (probably because all existing software would 
	   break) so for now we just make sure they're present but otherwise 
	   ignore them */
	if( cryptAlgo == CRYPT_ALGO_CAST )
		{
		readSequence( stream, NULL );
		readOctetString( stream, queryInfo->iv, &queryInfo->ivLength, 
						 CRYPT_MAX_IVSIZE );
		return( readShortInteger( stream, NULL ) );
		}
	if( cryptAlgo == CRYPT_ALGO_AES || cryptAlgo == CRYPT_ALGO_DES || \
		cryptAlgo == CRYPT_ALGO_3DES || cryptAlgo == CRYPT_ALGO_BLOWFISH )
		{
		if( cryptMode == CRYPT_MODE_ECB )
			return( readNull( stream ) );
		if( ( cryptMode == CRYPT_MODE_CBC ) || \
			( cryptAlgo == CRYPT_ALGO_AES && cryptMode == CRYPT_MODE_OFB ) )
			return( readOctetString( stream, queryInfo->iv, 
									 &queryInfo->ivLength, CRYPT_MAX_IVSIZE ) );
		readSequence( stream, NULL );
		readOctetString( stream, queryInfo->iv, &queryInfo->ivLength, 
						 CRYPT_MAX_IVSIZE );
		return( readShortInteger( stream, NULL ) );
		}
	if( cryptAlgo == CRYPT_ALGO_IDEA )
		{
		int paramTag;

		if( cryptMode == CRYPT_MODE_ECB )
			return( readNull( stream ) );
		readSequence( stream, NULL );
		paramTag = peekTag( stream );
		if( cryptMode == CRYPT_MODE_CFB )
			{
			/* Skip the CFB r, k, and j parameters */
			while( paramTag == MAKE_CTAG_PRIMITIVE( 0 ) || \
				   paramTag == MAKE_CTAG_PRIMITIVE( 1 ) || \
				   paramTag == MAKE_CTAG_PRIMITIVE( 2 ) )
				{
				long value;

				status = readShortIntegerTag( stream, &value, paramTag );
				if( cryptStatusError( status ) || value != 64 )
					return( CRYPT_ERROR_NOTAVAIL );
				paramTag = peekTag( stream );
				}
			return( readOctetStringTag( stream, queryInfo->iv, 
										&queryInfo->ivLength, 
										CRYPT_MAX_IVSIZE, 3 ) );
			}
		if( cryptMode == CRYPT_MODE_OFB && paramTag == BER_INTEGER )
			{
			long value;

			/* Skip the OFB j parameter */
			status = readShortInteger( stream, &value );
			if( cryptStatusError( status ) || value != 64 )
				return( CRYPT_ERROR_NOTAVAIL );
			}
		return( readOctetString( stream, queryInfo->iv, &queryInfo->ivLength, 
								 CRYPT_MAX_IVSIZE ) );
		}
	if( cryptAlgo == CRYPT_ALGO_RC2 )
		{
		/* In theory we should check that the parameter value == 
		   RC2_KEYSIZE_MAGIC (corresponding to a 128-bit key) but in practice 
		   this doesn't really matter, we just use whatever we find inside
		   the PKCS #1 padding */
		readSequence( stream, NULL );
		if( cryptMode != CRYPT_MODE_CBC )
			return( readShortInteger( stream, NULL ) );
		readShortInteger( stream, NULL );
		return( readOctetString( stream, queryInfo->iv, &queryInfo->ivLength, 
								 CRYPT_MAX_IVSIZE ) );
		}
	if( cryptAlgo == CRYPT_ALGO_RC4 )
		return( readNull( stream ) );
	if( cryptAlgo == CRYPT_ALGO_RC5 )
		{
		long val1, val2, val3;

		readSequence( stream, NULL );
		readShortInteger( stream, &val1 );			/* Version */
		readShortInteger( stream, &val2 );			/* Rounds */
		status = readShortInteger( stream, &val3 );	/* Block size */
		if( cryptStatusError( status ) || \
			val1 != 16 || val2 != 12 || val3 != 64 )
			/* This algorithm makes enough of a feature of its variable
			   parameters that we do actually check to make sure they're
			   sensible since it may just be possible that someone playing
			   with an implementation decides to use weird values */
			return( CRYPT_ERROR_NOTAVAIL );
		return( readOctetString( stream, queryInfo->iv, &queryInfo->ivLength, 
								 CRYPT_MAX_IVSIZE ) );
		}
	if( cryptAlgo == CRYPT_ALGO_SKIPJACK )
		{
		readSequence( stream, NULL );
		return( readOctetString( stream, queryInfo->iv, 
								 &queryInfo->ivLength, CRYPT_MAX_IVSIZE ) );
		}

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

/* Write an EncryptionAlgorithmIdentifier record */

static int writeContextCryptAlgoID( STREAM *stream, 
									const CRYPT_CONTEXT iCryptContext )
	{
	const BYTE *oid;
	BYTE iv[ CRYPT_MAX_IVSIZE ];
	CRYPT_ALGO_TYPE algorithm;
	CRYPT_MODE_TYPE mode;
	int oidSize, ivSize = 0, sizeofIV = 0, status;

	/* Extract the information 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;

⌨️ 快捷键说明

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