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

📄 asn1_ext.c

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

	return( CRYPT_ALGO_NONE );
	}

/* 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; algoIDinfoTbl[ i ].algorithm != CRYPT_ALGO_NONE; i++ )
		{
		const ALGOID_INFO *algoIDinfoPtr = &algoIDinfoTbl[ i ];

		if( algoIDinfoPtr->algorithm == algorithm && \
			algoIDinfoPtr->subAlgorithm == subAlgorithm )
			return( algoIDinfoPtr->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; algoIDinfoTbl[ i ].algorithm != CRYPT_ALGO_NONE; i++ )
		if( algoIDinfoTbl[ i ].algorithm == algorithm && \
			algoIDinfoTbl[ i ].subAlgorithm == subAlgorithm )
			return( algoIDinfoTbl[ i ].oid );

	return( NULL );
	}

/* Read the start of an AlgorithmIdentifier record, used by a number of 
   routines */

static int readAlgoIDheader( STREAM *stream, CRYPT_ALGO_TYPE *algorithm, 
							 CRYPT_ALGO_TYPE *subAlgorithm, int *extraLength,
							 const int tag )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	BYTE buffer[ MAX_OID_SIZE + 8 ];
	int bufferLength, cryptSubAlgo, length, status;

	/* Clear the return values */
	if( algorithm != NULL )
		*algorithm = CRYPT_ALGO_NONE;
	if( subAlgorithm != NULL )
		*subAlgorithm = CRYPT_ALGO_NONE;
	if( extraLength != NULL )
		*extraLength = 0;

	/* Determine the algorithm information based on the AlgorithmIdentifier
	   field */
	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 );
	length -= bufferLength;
	if( bufferLength != sizeofOID( buffer ) || length < 0 )
		/* It's a stream-related error, make it persistent */
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	if( ( cryptAlgo = oidToAlgorithm( buffer, \
									  &cryptSubAlgo ) ) == CRYPT_ALGO_NONE )
		return( CRYPT_ERROR_NOTAVAIL );
	if( algorithm != NULL )
		*algorithm = cryptAlgo;
	if( subAlgorithm != NULL )
		*subAlgorithm = cryptSubAlgo;

	/* If the user isn't interested in the algorithm parameters, skip them */
	if( extraLength == NULL )
		return( ( length > 0 ) ? sSkip( stream, length ) : CRYPT_OK );

	/* Handle any remaining parameters */
	if( length == sizeofNull() )
		return( readNull( stream ) );
	*extraLength = ( int ) length;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*					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: (Unsure where this one is from)
		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 somewhat haphazard 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/DigestAlgorithmIdentifier */

static int readAlgoIDInfo( STREAM *stream, QUERY_INFO *queryInfo, 
						   const int tag )
	{
	CRYPT_ALGO_TYPE mode;
	int length, status;

	/* Read the AlgorithmIdentifier header and OID.  Since this function has
	   to handle a variety of algorithm ID info, we have to cast the return
	   value to the appropriate enumerated type (some compilers complain 
	   about this) */
	status = readAlgoIDheader( stream, &queryInfo->cryptAlgo, &mode,
							   &length, tag );
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->cryptMode = ( CRYPT_MODE_TYPE ) mode;

	/* Some broken implementations use sign + hash algoIDs in places where
	   a hash algoID is called for, if we find one of these we modify the
	   read AlgorithmIdentifier information to make it look like a hash
	   algoID */
	if( ( queryInfo->cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
		  queryInfo->cryptAlgo <= CRYPT_ALGO_LAST_PKC ) && \
		( queryInfo->cryptMode >= CRYPT_ALGO_FIRST_HASH && \
		  queryInfo->cryptMode <= CRYPT_ALGO_LAST_HASH ) )
		{
		queryInfo->cryptAlgo = ( CRYPT_ALGO_TYPE ) queryInfo->cryptMode;
		queryInfo->cryptMode = ( CRYPT_ALGO_TYPE ) CRYPT_ALGO_NONE;
		}

	/* Hash 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_HASH && \
		  queryInfo->cryptAlgo <= CRYPT_ALGO_LAST_HASH ) || \
		( queryInfo->cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \
		  queryInfo->cryptAlgo <= CRYPT_ALGO_LAST_MAC ) )
		return( ( length > 0 ) ? sSkip( stream, length ) : CRYPT_OK );

	/* If it's not a hash/MAC algorithm, it has to be a conventional
	   encryption algorithm */
	if( queryInfo->cryptAlgo < CRYPT_ALGO_FIRST_CONVENTIONAL || \
		queryInfo->cryptAlgo > CRYPT_ALGO_LAST_CONVENTIONAL )
		return( CRYPT_ERROR_NOTAVAIL );

	/* Read the algorithm-specific 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 that 
	   they're present but otherwise ignore them */
	switch( queryInfo->cryptAlgo )
		{
		case CRYPT_ALGO_3DES:
		case CRYPT_ALGO_AES:
		case CRYPT_ALGO_BLOWFISH:
		case CRYPT_ALGO_DES:
			if( queryInfo->cryptMode == CRYPT_MODE_ECB )
				/* The NULL parameter has already been read in 
				   readAlgoIDheader() */
				return( CRYPT_OK );
			if( ( queryInfo->cryptMode == CRYPT_MODE_CBC ) || \
				( queryInfo->cryptAlgo == CRYPT_ALGO_AES && \
				  queryInfo->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 ) );

		case CRYPT_ALGO_CAST:
			readSequence( stream, NULL );
			readOctetString( stream, queryInfo->iv, &queryInfo->ivLength, 
							 CRYPT_MAX_IVSIZE );
			return( readShortInteger( stream, NULL ) );

		case CRYPT_ALGO_IDEA:
			{
			int paramTag;

			if( queryInfo->cryptMode == CRYPT_MODE_ECB )
				/* The NULL parameter has already been read in 
				   readAlgoIDheader() */
				return( CRYPT_OK );
			readSequence( stream, NULL );
			paramTag = peekTag( stream );
			if( queryInfo->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 ) )
						return( status );
					if( value != 64 )
						return( CRYPT_ERROR_NOTAVAIL );
					paramTag = peekTag( stream );
					}
				return( readOctetStringTag( stream, queryInfo->iv, 
											&queryInfo->ivLength, 
											CRYPT_MAX_IVSIZE, 3 ) );
				}
			if( queryInfo->cryptMode == CRYPT_MODE_OFB && \
				paramTag == BER_INTEGER )
				{
				long value;

				/* Skip the OFB j parameter */
				status = readShortInteger( stream, &value );
				if( cryptStatusError( status ) )
					return( status );
				if( value != 64 )
					return( CRYPT_ERROR_NOTAVAIL );
				}
			return( readOctetString( stream, queryInfo->iv, 
									 &queryInfo->ivLength, 
									 CRYPT_MAX_IVSIZE ) );
			}

		case 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( queryInfo->cryptMode != CRYPT_MODE_CBC )
				return( readShortInteger( stream, NULL ) );
			readShortInteger( stream, NULL );
			return( readOctetString( stream, queryInfo->iv, 
									 &queryInfo->ivLength, 
									 CRYPT_MAX_IVSIZE ) );

		case CRYPT_ALGO_RC4:
			/* The NULL parameter has already been read in 
			   readAlgoIDheader() */
			return( CRYPT_OK );

		case 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 ) )
				return( status );
			if( 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 that 
				   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 ) );
			}

		case CRYPT_ALGO_SKIPJACK:
			readSequence( stream, NULL );
			return( readOctetString( stream, queryInfo->iv, 
									 &queryInfo->ivLength, 
									 CRYPT_MAX_IVSIZE ) );
		}

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

/* Write an EncryptionAlgorithmIdentifier record */

static int writeContextCryptAlgoID( STREAM *stream, 
									const CRYPT_CONTEXT iCryptContext )
	{
	const BYTE *oid;

⌨️ 快捷键说明

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