📄 asn1_rd.c
字号:
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 + -