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

📄 misc_rw.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*				Miscellaneous (Non-ASN.1) Read/Write Routines				*
*						Copyright Peter Gutmann 1992-2004					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "crypt.h"
  #include "bn.h"
  #include "misc_rw.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../bn/bn.h"
  #include "misc_rw.h"
#else
  #include "crypt.h"
  #include "bn/bn.h"
  #include "misc/misc_rw.h"
#endif /* Compiler-specific includes */

/****************************************************************************
*																			*
*								Utility Routines							*
*																			*
****************************************************************************/

/* Read large integer data */

typedef enum { LENGTH_16U, LENGTH_16U_BITS, 
			   LENGTH_32, LENGTH_32U_BITS } LENGTH_TYPE;

static int readInteger( STREAM *stream, void *integer, int *integerLength, 
						const int minLength, const int maxLength, 
						const LENGTH_TYPE lengthType )
	{
	int length;

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

	/* Clear return values */
	if( integer != NULL )
		{
		*( ( BYTE * ) integer ) = '\0';
		*integerLength = 0;
		}

	/* Read the length and make sure that it's within range, with allowance 
	   for extra zero-padding */
	if( lengthType == LENGTH_16U || lengthType == LENGTH_16U_BITS )
		length = readUint16( stream );
	else
		length = readUint32( stream );
	if( cryptStatusError( length ) )
		return( length );
	if( lengthType == LENGTH_16U_BITS || lengthType == LENGTH_32U_BITS )
		length = bitsToBytes( length );
	if( length < minLength || length > maxLength + 2 )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );

	/* If we're reading a signed integer, the sign bit can't be set, since 
	   this would produce a negative value.  This differs from the ASN.1 
	   code, where the incorrect setting of the sign bit is so common that 
	   we always treat integers as unsigned */
	if( lengthType == LENGTH_32 && ( sPeek( stream ) & 0x80 ) )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );

	/* Skip possible leading-zero padding and repeat the length check once
	   the zero-padding has been adjusted */
	while( length > 0 && sPeek( stream ) == 0 )
		{
		int status;

		status = sgetc( stream );
		if( cryptStatusError( status ) )
			return( status );
		length--;
		}
	if( length < minLength || length > maxLength )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	
	/* Read the value */
	if( integer == NULL ) 
		return( sSkip( stream, length ) );
	*integerLength = length;
	return( sread( stream, integer, length ) );
	}

/****************************************************************************
*																			*
*								Data Read Routines							*
*																			*
****************************************************************************/

/* Read 16-, 32- and 64-bit integer values.  Although in theory we could do 
   the 16-bit read more simply with ( sgetc( stream ) << 8 ) | sgetc( stream ), 
   this will break with some compilers that reorder expressions */

int readUint16( STREAM *stream )
	{
	BYTE buffer[ UINT16_SIZE + 8 ];
	int status;

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

	status = sread( stream, buffer, UINT16_SIZE );
	if( cryptStatusError( status ) )
		return( status );
	return( ( ( int ) buffer[ 0 ] << 8 ) | buffer[ 1 ] );
	}

int readUint32( STREAM *stream )
	{
	BYTE buffer[ UINT32_SIZE + 8 ];
	int status;

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

	status = sread( stream, buffer, UINT32_SIZE );
	if( cryptStatusError( status ) )
		return( status );
	if( buffer[ 0 ] & 0x80 )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	return( ( ( int ) buffer[ 0 ] << 24 ) | \
			( ( int ) buffer[ 1 ] << 16 ) | \
			( ( int ) buffer[ 2 ] << 8 ) | \
							   buffer[ 3 ] );
	}

int readUint64( STREAM *stream )
	{
	BYTE buffer[ ( UINT64_SIZE / 2 ) + 8 ];
	int status;

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

	status = sread( stream, buffer, UINT64_SIZE / 2 );
	if( cryptStatusError( status ) )
		return( status );
	if( memcmp( buffer, "\x00\x00\x00\x00", UINT64_SIZE / 2 ) )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	return( readUint32( stream ) );
	}

/* Read 32- and 64-bit time values.  Note that we can't just call down 
   directly to readUint32() for these since time_t may be unsigned or of a 
   different integral size than int */

int readUint32Time( STREAM *stream, time_t *timeVal )
	{
	int value;

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

	value = readUint32( stream );
	if( cryptStatusError( value ) )
		return( value );
	*timeVal = ( time_t ) value;
	return( CRYPT_OK );
	}

int readUint64Time( STREAM *stream, time_t *timeVal )
	{
	int value;

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

	value = readUint64( stream );
	if( cryptStatusError( value ) )
		return( value );
	*timeVal = ( time_t ) value;
	return( CRYPT_OK );
	}

/* Read a string preceded by a 32-bit length */

int readString32( STREAM *stream, void *string, int *stringLength,
				  const int maxLength )
	{
	int length;

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

	/* Clear return values */
	if( string != NULL )
		{
		( ( char * ) string )[ 0 ] = '\0';
		*stringLength = 0;
		}

	/* Read the string, limiting the size to the maximum buffer size */
	length = readUint32( stream );
	if( length <= 0 )
		return( length );	/* Error or zero length */
	if( length > maxLength )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	if( string == NULL )
		return( sSkip( stream, length ) );
	*stringLength = length;
	return( sread( stream, string, length ) );
	}

/* Read a raw object preceded by a 32-bit length */

int readRawObject32( STREAM *stream, void *buffer, int *bufferLength,
					 const int maxLength )
	{
	BYTE *bufPtr = buffer;
	int length;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( ( buffer == NULL && bufferLength == NULL ) || \
			( isWritePtr( buffer, maxLength ) && 
			  isWritePtr( bufferLength, sizeof( int ) ) ) );
	assert( maxLength >= UINT32_SIZE + 1 );

	/* Clear return values */
	if( buffer != NULL )
		{
		memset( buffer, 0, UINT32_SIZE );
		*bufferLength = 0;
		}

	/* Read the string, limiting the size to the maximum buffer size */
	length = readUint32( stream );
	if( length <= 0 )
		/* Error or zero length.  If it's zero length we don't return any
		   data */
		return( length );
	if( length > maxLength - UINT32_SIZE )
		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
	bufPtr[ 0 ] = ( length >> 24 ) & 0xFF;
	bufPtr[ 1 ] = ( length >> 16 ) & 0xFF;
	bufPtr[ 2 ] = ( length >> 8 ) & 0xFF;
	bufPtr[ 3 ] = length & 0xFF;
	if( buffer == NULL )
		return( sSkip( stream, length ) );
	*bufferLength = length + UINT32_SIZE;
	return( sread( stream, bufPtr + UINT32_SIZE, length ) );
	}

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

static int readUniversal( STREAM *stream, const LENGTH_TYPE lengthType )
	{
	int length;

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

	/* Read the length and skip the data */
	if( lengthType == LENGTH_16U )
		length = readUint16( stream );
	else
		length = readUint32( stream );
	if( length <= 0 )
		/* Error or zero length */
		return( length );
	return( sSkip( stream, length ) );
	}

int readUniversal16( STREAM *stream )
	{
	return( readUniversal( stream, LENGTH_16U ) );
	}

int readUniversal32( STREAM *stream )
	{
	return( readUniversal( stream, LENGTH_32 ) );
	}

/* Read (large) integers in various formats */

int readInteger16U( STREAM *stream, void *integer, int *integerLength,
					const int minLength, const int maxLength )
	{
	return( readInteger( stream, integer, integerLength, minLength, 
						 maxLength, LENGTH_16U ) );
	}

int readInteger16Ubits( STREAM *stream, void *integer, int *integerLength,
						const int minLength, const int maxLength )
	{
	return( readInteger( stream, integer, integerLength, minLength, 
						 maxLength, LENGTH_16U_BITS ) );
	}

int readInteger32( STREAM *stream, void *integer, int *integerLength,
				   const int minLength, const int maxLength )
	{
	return( readInteger( stream, integer, integerLength, minLength, 
						 maxLength, LENGTH_32 ) );
	}

int readInteger32Ubits( STREAM *stream, void *integer, int *integerLength,
						const int minLength, const int maxLength )
	{
	return( readInteger( stream, integer, integerLength, minLength, 
						 maxLength, LENGTH_32U_BITS ) );
	}

/* Read bignum integers in various formats */

static int readBignumInteger( STREAM *stream, void *bignum, 
							  const int minLength, const int maxLength,
							  const LENGTH_TYPE lengthType )
	{
	BYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];
	int length, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( bignum, sizeof( BIGNUM ) ) );
	assert( minLength >= 1 && maxLength <= CRYPT_MAX_PKCSIZE );

	/* Read the integer data */
	status = readInteger( stream, buffer, &length, minLength, maxLength, 
						  lengthType );
	if( cryptStatusError( status ) )
		return( status );

	/* Convert the value to a bignum */
	if( BN_bin2bn( buffer, length, bignum ) == NULL )
		{
		sSetError( stream, CRYPT_ERROR_MEMORY );
		status = CRYPT_ERROR_MEMORY;
		}
	zeroise( buffer, CRYPT_MAX_PKCSIZE );
	return( status );
	}

int readBignumInteger16U( STREAM *stream, void *bignum, const int minLength, 
						  const int maxLength )
	{
	return( readBignumInteger( stream, bignum, minLength, maxLength, 
							   LENGTH_16U ) );
	}

int readBignumInteger16Ubits( STREAM *stream, void *bignum, const int minBits, 
							  const int maxBits )
	{
	return( readBignumInteger( stream, bignum, bitsToBytes( minBits ), 
							   bitsToBytes( maxBits ), LENGTH_16U_BITS ) );
	}

int readBignumInteger32( STREAM *stream, void *bignum, const int minLength, 
						 const int maxLength )
	{
	return( readBignumInteger( stream, bignum, minLength, maxLength, 
							   LENGTH_32 ) );
	}

/****************************************************************************
*																			*
*								Data Write Routines							*
*																			*
****************************************************************************/

/* Write 16-, 32- and 64-bit integer values */

int writeUint16( STREAM *stream, const int value )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	sputc( stream, ( value >> 8 ) & 0xFF );
	return( sputc( stream, value & 0xFF ) );
	}

⌨️ 快捷键说明

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