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

📄 asn1.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		for( i = 0; i < noLengthOctets && !buffer[ i ]; i++ );
		if( noLengthOctets - i > ( shortLen ? 2 : 4 ) )
			{
			/* > 32-bit length, this should never happen */
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( CRYPT_ERROR_BADDATA );
			}
		if( i >= noLengthOctets )
			return( 0 );		/* Very broken encoding of a zero length */
		bufPtr = buffer + i;
		}
	else
		if( noLengthOctets > ( shortLen ? 2 : 4 ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( CRYPT_ERROR_BADDATA );
			}
	length = 0;
	while( noLengthOctets-- > 0 )
		length = length << 8 | *bufPtr++;
	if( length & ( shortLen ? 0xFFFF8000UL : 0xC0000000UL ) )
		{
		/* Length must be < 1GB for standard data, < 32K for short lengths */
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( CRYPT_ERROR_BADDATA );
		}

	return( length );
	}

/* Read a constrained-length data value, used by several routines */

static int readConstrainedData( STREAM *stream, BYTE *buffer, 
								int *bufferLength, const int length,
								const int maxLength )
	{
	int dataLength = length, remainder = 0;

	if( bufferLength != NULL )
		*bufferLength = length;

	/* If we don't care about the return value, skip it and exit */
	if( buffer == NULL )
		return( sSkip( stream, dataLength ) );

	/* Read in the object, limiting the size to the maximum buffer size */
	if( dataLength > maxLength )
		{
		remainder = dataLength - maxLength;
		dataLength = maxLength;
		}
	if( dataLength > 0 )
		sread( stream, buffer, dataLength );

	/* Read in any remaining data if necessary */
	if( remainder > 0 )
		sSkip( stream, remainder );

	return( sGetStatus( stream ) );
	}

/* Read a short (<= 256 bytes) raw object without decoding it.  This is used
   to read short data blocks like object identifiers which are only ever
   handled in encoded form */

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

	/* 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 readShortLength() for the length, 
	   but since we only need to handle lengths which can be encoded in one 
	   or two bytes this isn't much of a problem */
	if( expectedTag != NO_TAG )
		{
		const int tag = readTag( stream );

		if( expectedTag != CRYPT_UNUSED && expectedTag != tag )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		buffer[ offset++ ] = tag;
		}
	length = sgetc( stream );
	buffer[ offset++ ] = length;
	if( length & 0x80 )
		{
		if( ( length & 0x7F ) > 1 )
			{
			/* If the object is longer than 256 bytes, we don't want to 
			   handle it */
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		length = sgetc( stream );
		buffer[ offset++ ] = length;
		}
	if( cryptStatusError( length ) )
		return( length );

	/* Read in the rest of the data, adjusting the length for the header data
	   which we've already read */
	status = readConstrainedData( stream, buffer + offset, bufferLength, 
								  length, maxLength - offset );
	if( cryptStatusOK( status ) )
		*bufferLength += offset;
	return( status );
	}

/* Read a (short) numeric value, used by several routines */

static int readNumeric( STREAM *stream, long *value )
	{
	BYTE buffer[ 8 ], *bufPtr = buffer;
	int length, status;

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

	/* Read the length field and make sure it's a short value, and read the 
	   data */
	length = sgetc( stream );
	if( length <= 0 )
		return( length );	/* Error or zero length */
	if( length > 4 )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( CRYPT_ERROR_BADDATA );
		}
	status = sread( stream, buffer, length );
	if( cryptStatusError( status ) || value == NULL )
		return( status );
	while( length-- > 0 )
		*value = ( *value << 8 ) | *bufPtr++;

	return( CRYPT_OK );
	}

/* Read a bignum integer value */

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

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

	/* Read the identifier field if necessary and the length */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_INTEGER ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}
	length = readShortLength( stream );
	if( length <= 0 )
		return( length );	/* Error or zero length */

	/* ASN.1 encoded values are signed while the internal representation is
	   unsigned, so we skip any leading zero bytes needed to encode a value
	   which has the high bit set */
	if( sgetc( stream ) )
		sungetc( stream );	/* It's not zero, put it back */
	else
		length--;			/* Skip the zero byte */
	if( length == 0 )
		return( CRYPT_OK );	/* Zero value */

	/* 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 universal type and discard it (used to skip unknown or unwanted
   types) */

int readUniversalData( STREAM *stream )
	{
	int length;

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

int readUniversal( STREAM *stream )
	{
	readTag( stream );
	return( readUniversalData( stream ) );
	}

/* Read a short integer value */

int readShortIntegerTag( STREAM *stream, long *value, const int tag )
	{
	/* Clear return value */
	if( value != NULL )
		*value = 0L;

	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_INTEGER ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Read the numeric field */
	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;

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

	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_ENUMERATED ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Read the numeric field */
	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 )
	{
	/* Read the identifier if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_NULL ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Skip the length octet */
	if( sgetc( stream ) )
		sSetError( stream, CRYPT_ERROR_BADDATA );
	return( sGetStatus( stream ) );
	}

/* Read a boolean value */

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

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

	/* Read the identifier if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_BOOLEAN ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Skip the length octet and read the boolean value */
	if( sgetc( stream ) != 1 )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( sGetStatus( stream ) );
		}
	value = sgetc( stream );
	if( !cryptStatusError( value ) && boolean != NULL )
		*boolean = value ? TRUE : FALSE;
	return( sGetStatus( stream ) );
	}

/* Read an octet string value */

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

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

	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_OCTETSTRING ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Now read in the string, limiting the size to the maximum buffer size */
	length = readShortLength( stream );
	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;
	
	/* Clear return value */
	if( bitString != NULL )
		*bitString = 0;

	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_BITSTRING ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Make sure we have a bitstring with between 0 and sizeof( int ) bits.
	   This isn't as machine-dependant as it seems, the only place where
	   bit strings longer than one or two bytes are used is with the more
	   obscure CMP error subcodes which just provide further information
	   above and beyond the main error code and text message, so we provide
	   the extra information if the machine architecture can handle it and
	   skip it otherwise */
	length = sgetc( stream ) - 1;
	noBits = sgetc( stream );
	if( length < 0 || length > sizeof( int ) || noBits < 0 || noBits > 7 )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( CRYPT_ERROR_BADDATA );
		}
	if( length == 0 )
		return( CRYPT_OK );		/* Zero value */
	noBits = ( length * 8 ) - noBits;

	/* ASN.1 bitstrings start at bit 0, so we need to reverse the order of
	   the bits */
	data = sgetc( stream );
	for( i = noBits - 8; i > 0; i -= 8 )
		{
		data = ( data << 8 ) | sgetc( stream );
		mask <<= 8;
		}
	for( i = 0; i < noBits; i++ )
		{

⌨️ 快捷键说明

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