📄 misc_rw.c
字号:
/****************************************************************************
* *
* Miscellaneous (Non-ASN.1) Read/Write Routines *
* Copyright Peter Gutmann 1992-2003 *
* *
****************************************************************************/
/* Non-ASN.1 formats use their own encoding types for integers, strings,
and misellaneous other values, the following functions read and write
these values */
#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 */
#if defined( USE_PGP ) || defined( USE_PGPKEYS ) || \
defined( USE_SSH1 ) || defined( USE_SSH2 )
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Read a constrained-length data value, used by several routines */
static int readConstrainedData( STREAM *stream, void *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 );
*bufferLength = dataLength;
}
/* Skip any remaining data if necessary */
if( remainder > 0 )
sSkip( stream, remainder );
return( sGetStatus( stream ) );
}
/* Read large integer data */
typedef enum { LENGTH_16BITS_BITS, LENGTH_32BITS, LENGTH_32BITS_BITS } LENGTH_TYPE;
static int readIntegerData( STREAM *stream, void *integer,
int *integerLength, const int minLength,
const int maxLength,
const LENGTH_TYPE lengthType )
{
BYTE *integerDataPtr = integer;
int length, i, status;
/* Clear return values */
if( integer != NULL )
*integerDataPtr = '\0';
if( integerLength != NULL )
*integerLength = 0;
/* Read the integer value */
if( lengthType == LENGTH_16BITS_BITS )
{
const int bitLength = ( sgetc( stream ) << 8 ) | sgetc( stream );
length = bitsToBytes( bitLength );
if( cryptStatusError( sGetStatus( stream ) ) )
return( sGetStatus( stream ) );
}
else
{
length = readUint32( stream );
if( cryptStatusError( length ) )
return( length );
if( lengthType == LENGTH_32BITS_BITS )
length = bitsToBytes( length );
}
if( length < minLength || length > maxLength )
{
sSetError( stream, CRYPT_ERROR_BADDATA );
return( CRYPT_ERROR_BADDATA );
}
if( integerLength != NULL )
*integerLength = length;
if( integer == NULL )
return( sSkip( stream, length ) );
status = sread( stream, integer, length );
if( cryptStatusError( status ) )
return( status );
/* Strip possible leading-zero padding */
for( i = 0; integerDataPtr[ i ] == 0 && i < length; i++ );
if( i > 0 )
{
if( length - i <= 0 )
{
sSetError( stream, CRYPT_ERROR_BADDATA );
return( CRYPT_ERROR_BADDATA );
}
memmove( integerDataPtr, integerDataPtr + i, length - i );
if( integerLength != NULL )
*integerLength = length;
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Data Read/Write Routines *
* *
****************************************************************************/
/* Read and write 32-bit integer values */
int readUint32( STREAM *stream )
{
BYTE buffer[ UINT32_SIZE ];
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
status = sread( stream, buffer, UINT32_SIZE );
if( cryptStatusError( status ) )
return( status );
if( buffer[ 0 ] & 0x80 )
{
sSetError( stream, CRYPT_ERROR_BADDATA );
return( CRYPT_ERROR_BADDATA );
}
return( ( ( unsigned int ) buffer[ 0 ] << 24 ) | \
( ( unsigned int ) buffer[ 1 ] << 16 ) | \
( ( unsigned int ) buffer[ 2 ] << 8 ) | \
buffer[ 3 ] );
}
int writeUint32( STREAM *stream, const int value )
{
BYTE buffer[ UINT32_SIZE ];
assert( isWritePtr( stream, sizeof( STREAM ) ) );
buffer[ 0 ] = value >> 24;
buffer[ 1 ] = value >> 16;
buffer[ 2 ] = value >> 8;
buffer[ 3 ] = value & 0xFF;
return( swrite( stream, buffer, UINT32_SIZE ) );
}
/* Read and write 64-bit integer values standard integer values */
int readUint64( STREAM *stream )
{
BYTE buffer[ UINT64_SIZE / 2 ];
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 ) )
{
sSetError( stream, CRYPT_ERROR_BADDATA );
return( CRYPT_ERROR_BADDATA );
}
return( readUint32( stream ) );
}
int writeUint64( STREAM *stream, const int value )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
swrite( stream, "\x00\x00\x00\x00", UINT64_SIZE / 2 );
return( writeUint32( stream, value ) );
}
/* Read and write 32- and 64-bit time values. Note that we can't call down
to read/writeUint32 for these since time_t may be unsigned or of a
different integral size than int */
int readUint32Time( STREAM *stream, time_t *timeVal )
{
BYTE buffer[ UINT32_SIZE ];
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( timeVal, sizeof( time_t ) ) );
status = sread( stream, buffer, UINT32_SIZE );
if( cryptStatusError( status ) )
return( status );
if( timeVal != NULL )
*timeVal = ( ( time_t ) buffer[ 0 ] << 24 ) | \
( ( time_t ) buffer[ 1 ] << 16 ) | \
( ( time_t ) buffer[ 2 ] << 8 ) | \
buffer[ 3 ];
return( CRYPT_OK );
}
int writeUint32Time( STREAM *stream, const time_t timeVal )
{
BYTE buffer[ UINT32_SIZE ];
assert( isWritePtr( stream, sizeof( STREAM ) ) );
buffer[ 0 ] = ( int ) ( timeVal >> 24 );
buffer[ 1 ] = ( int ) ( timeVal >> 16 );
buffer[ 2 ] = ( int ) ( timeVal >> 8 );
buffer[ 3 ] = ( int ) ( timeVal & 0xFF );
return( swrite( stream, buffer, UINT32_SIZE ) );
}
int readUint64Time( STREAM *stream, time_t *timeVal )
{
BYTE buffer[ UINT64_SIZE ];
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( timeVal, sizeof( time_t ) ) );
status = sread( stream, buffer, UINT64_SIZE );
if( cryptStatusError( status ) )
return( status );
if( memcmp( buffer, "\x00\x00\x00\x00", UINT64_SIZE / 2 ) )
{
sSetError( stream, CRYPT_ERROR_BADDATA );
return( CRYPT_ERROR_BADDATA );
}
return( readUint32Time( stream, timeVal ) );
}
int writeUint64Time( STREAM *stream, const time_t timeVal )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
swrite( stream, "\x00\x00\x00\x00", UINT64_SIZE / 2 );
return( writeUint32Time( stream, timeVal ) );
}
/* Read and write strings preceded by 32-bit lengths */
int readString32( STREAM *stream, void *string, int *stringLength,
const int maxLength )
{
int length;
/* Clear return values */
if( string != NULL )
( ( char * ) string )[ 0 ] = '\0';
if( stringLength != NULL )
*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 */
return( readConstrainedData( stream, string, stringLength, length,
maxLength ) );
}
int writeString32( STREAM *stream, const void *string,
const int stringLength )
{
const int length = ( stringLength ) ? stringLength : strlen( string );
writeUint32( stream, length );
return( swrite( stream, string, length ) );
}
/* Read and write (large) integers preceded by 32-bit lengths */
int readInteger32( STREAM *stream, void *integer, int *integerLength,
const int maxLength )
{
return( readIntegerData( stream, integer, integerLength, 1, maxLength,
LENGTH_32BITS ) );
}
int writeInteger32( STREAM *stream, const void *integer,
const int integerLength )
{
const BOOLEAN leadingOneBit = ( ( BYTE * ) integer )[ 0 ] & 0x80;
writeUint32( stream, integerLength + ( leadingOneBit ? 1 : 0 ) );
if( leadingOneBit )
sputc( stream, 0 ); /* MPIs are signed values */
return( swrite( stream, integer, integerLength ) );
}
/* Read and write unsigned (large) integers preceded by 16- and 32-bit
lengths, lengths in bits */
int readInteger16Ubits( STREAM *stream, void *integer, int *integerLength,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -