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

📄 asn1_rd.c

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

int readRawObjectTag( STREAM *stream, BYTE *buffer, int *bufferLength,
					  const int maxLength, const int tag )
	{
	int length, offset = 0;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( buffer, maxLength ) );
	assert( isWritePtr( bufferLength, sizeof( int ) ) );

	/* Clear return value */
	*buffer = '\0';
	*bufferLength = 0;

	/* Read the identifier field and length.  Since we need to remember each
	   byte as it's read we can't just call readLengthValue() for the length, 
	   but since we only need to handle lengths that can be encoded in one 
	   or two bytes this isn't a problem */
	if( tag != NO_TAG )
		{
		const int objectTag = readTag( stream );

		if( tag != CRYPT_UNUSED && tag != objectTag )
			return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
		if( buffer != NULL )
			buffer[ offset++ ] = objectTag;
		}
	length = sgetc( stream );
	if( cryptStatusError( length ) )
		return( length );
	buffer[ offset++ ] = length;
	if( length & 0x80 )
		{
		/* If the object is indefinite-length or longer than 256 bytes (i.e. 
		   the length-of-length is anything other than 1), we don't want to 
		   handle it */
		if( length != 0x81 )
			return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
		length = sgetc( stream );
		if( cryptStatusError( length ) )
			return( length );
		buffer[ offset++ ] = length;
		}
	if( offset + length > maxLength )
		return( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );

	/* Read in the rest of the data */
	*bufferLength = offset + length;
	return( ( length <= 0 ) ? \
			CRYPT_OK : sread( stream, buffer + offset, length ) );
	}

/* Read a large integer value */

int readIntegerTag( STREAM *stream, BYTE *integer, int *integerLength,
					const int maxLength, const int tag )
	{
	int length;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( integer == NULL || isWritePtr( integer, maxLength ) );
	assert( integerLength == NULL || \
			isWritePtr( integerLength, sizeof( int ) ) );
	assert( maxLength > 0 );

	/* Clear return value */
	if( integer != NULL )
		*integer = '\0';
	if( integerLength != NULL )
		*integerLength = 0;

	/* Read the integer header info */
	length = readIntegerHeader( stream, tag );
	if( length <= 0 )
		return( length );	/* Error or zero length */

	/* Read in the numeric value, limiting the size to the maximum buffer 
	   size.  This is safe because the only situation where this can occur 
	   is when reading some blob (whose value we don't care about) dressed 
	   up as an integer rather than for any real integer */
	return( readConstrainedData( stream, integer, integerLength, length, 
								 maxLength ) );
	}

/* Read a bignum integer value */

int readBignumTag( STREAM *stream, void *bignum, const int tag )
	{
	BYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];
	int length, status;

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

	/* Read the integer header info */
	length = readIntegerHeader( stream, tag );
	if( length <= 0 )
		return( length );	/* Error or zero length */

	/* Read the value into a fixed buffer */
	if( length > CRYPT_MAX_PKCSIZE )
		return( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );
	status = sread( stream, buffer, length );
	if( !cryptStatusError( status ) )
		{
		if( BN_bin2bn( buffer, length, bignum ) == NULL )
			{
			sSetError( stream, CRYPT_ERROR_MEMORY );
			status = CRYPT_ERROR_MEMORY;
			}
		zeroise( buffer, CRYPT_MAX_PKCSIZE );
		}
	return( status );
	}

/* Read a universal type and discard it (used to skip unknown or unwanted
   types) */

int readUniversalData( STREAM *stream )
	{
	int length;

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

	length = readLengthValue( stream, READLENGTH_SHORT );
	if( length <= 0 )
		return( length );	/* Error or zero length */
	return( sSkip( stream, length ) );
	}

int readUniversal( STREAM *stream )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	readTag( stream );
	return( readUniversalData( stream ) );
	}

/* Read a short integer value */

int readShortIntegerTag( STREAM *stream, long *value, const int tag )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( value == NULL || isWritePtr( value, sizeof( long ) ) );

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

	if( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_INTEGER ) )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	return( readNumeric( stream, value ) );
	}

/* Read an enumerated value.  This is encoded like an ASN.1 integer so we
   just read it as such */

int readEnumeratedTag( STREAM *stream, int *enumeration, const int tag )
	{
	long value;
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( enumeration == NULL || \
			isWritePtr( enumeration, sizeof( int ) ) );

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

	if( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_ENUMERATED ) )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	status = readNumeric( stream, &value );
	if( cryptStatusOK( status ) && enumeration != NULL )
		*enumeration = ( int ) value;
	return( status );
	}

/* Read a null value */

int readNullTag( STREAM *stream, const int tag )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Read the identifier if necessary */
	if( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_NULL ) )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	if( sgetc( stream ) != 0 )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	return( CRYPT_OK );
	}

/* Read a boolean value */

int readBooleanTag( STREAM *stream, BOOLEAN *boolean, const int tag )
	{
	int value;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( boolean == NULL || \
			isWritePtr( boolean, sizeof( BOOLEAN ) ) );

	/* Clear return value */
	if( boolean != NULL )
		*boolean = FALSE;

	if( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_BOOLEAN ) )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	if( sgetc( stream ) != 1 )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	value = sgetc( stream );
	if( cryptStatusError( value ) )
		return( value );
	if( boolean != NULL )
		*boolean = value ? TRUE : FALSE;
	return( CRYPT_OK );
	}

/* Read an OID and check it against a permitted value or a selection of 
   permitted values */

int readOIDEx( STREAM *stream, const OID_INFO *oidSelection, 
			   const OID_INFO **oidSelectionValue )
	{
	static const OID_INFO nullOidSelection = { NULL, CRYPT_ERROR, NULL };
	BYTE buffer[ MAX_OID_SIZE + 8 ];
	int length, oidEntry, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( oidSelection, sizeof( OID_INFO ) * 2 ) );
	assert( isReadPtr( oidSelectionValue, sizeof( OID_INFO * ) ) );

	/* Clear return value */
	if( oidSelectionValue != NULL )
		*oidSelectionValue = &nullOidSelection;

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

	/* 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 )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );

	if( oidSelectionValue != NULL )
		*oidSelectionValue = &oidSelection[ oidEntry ];
	return( CRYPT_OK );
	}

int readOID( STREAM *stream, const OID_INFO *oidInfo, int *selectionID )
	{
	const OID_INFO *oidSelectionInfo;
	int status;

	/* Clear return value */
	*selectionID = CRYPT_ERROR;

	status = readOIDEx( stream, oidInfo, &oidSelectionInfo );
	if( cryptStatusOK( status ) )
		*selectionID = oidSelectionInfo->selectionID;
	return( status );
	}

int readFixedOID( STREAM *stream, const BYTE *oid )
	{
	const OID_INFO *dummy;
	CONST_INIT_STRUCT_A2( OID_INFO oidInfo[ 2 ], oid, NULL );

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

	/* Set up a one-entry OID_INFO list to pass down to readOID() */
	CONST_SET_STRUCT_A( memset( oidInfo, 0, sizeof( OID_INFO ) * 2 ); \
						oidInfo[ 0 ].oid = oid );
	return( readOIDEx( stream, oidInfo, &dummy ) );
	}

/* Read an octet string value */

int readOctetStringTag( STREAM *stream, BYTE *string, int *stringLength,
						const int maxLength, const int tag )
	{
	int length;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( string == NULL || isWritePtr( string, maxLength ) );
	assert( stringLength == NULL || \
			isWritePtr( stringLength, sizeof( int ) ) );
	assert( maxLength > 0 );

	/* Clear return value */
	if( string != NULL )
		{
		*string = '\0';
		*stringLength = 0;
		}

	/* Read the string, limiting the size to the maximum buffer size */
	if( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_OCTETSTRING ) )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	length = readLengthValue( stream, READLENGTH_SHORT );
	if( length <= 0 )
		return( length );	/* Error or zero length */
	return( readConstrainedData( stream, string, stringLength, length, 
								 maxLength ) );
	}

/* Read a character string.  This handles any of the myriad ASN.1 character
   string types.  The handling of the tag works somewhat differently here to
   the usual manner in that since the function is polymorphic, the tag
   defines the character string type and is always used (there's no
   NO_TAG or DEFAULT_TAG like the other functions use).  This works because
   the plethora of string types means that the higher-level routines that 
   read them invariably have to sort out the valid tag types themselves */

int readCharacterString( STREAM *stream, BYTE *string, int *stringLength,
						 const int maxLength, const int tag )
	{
	int length;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( string == NULL || isWritePtr( string, maxLength ) );
	assert( stringLength == NULL || \
			isWritePtr( stringLength, sizeof( int ) ) );
	assert( maxLength > 0 );
	assert( tag != NO_TAG && tag != DEFAULT_TAG );

	/* Clear return value */
	if( string != NULL )
		{
		*string = '\0';
		*stringLength = 0;
		}

	/* Read the string, limiting the size to the maximum buffer size */
	if( readTag( stream ) != tag )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	length = readLengthValue( stream, READLENGTH_SHORT );
	if( length <= 0 )
		return( length );	/* Error or zero length */
	return( readConstrainedData( stream, string, stringLength, length, 
								 maxLength ) );
	}

/* Read a bit string */

int readBitStringTag( STREAM *stream, int *bitString, const int tag )
	{
	unsigned int data, mask = 0x80;
	int length, flag = 1, value = 0, noBits, i;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( bitString == NULL || isWritePtr( bitString, sizeof( int ) ) );
	

⌨️ 快捷键说明

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